Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit65297c6

Browse files
crisbetoalxhub
authored andcommitted
fix(compiler-cli): expand type for native controls with a dynamic type
We recently allowed users to have a dynamic input `type` with signal forms, but the logic that infers the value type falls back to `string` even though in theory it can be any of the other types.These changes expand the inferred type to `string | number | boolean | Date | null` if we detect a dynamic `type` binding.(cherry picked from commit8a3f3a9)
1 parent6d74755 commit65297c6

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

‎packages/compiler-cli/src/ngtsc/typecheck/src/ops/signal_forms.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,25 @@ export class TcbNativeFieldOp extends TcbOp {
157157
]);
158158
}
159159

160+
consthasDynamicType=
161+
this.inputType===null&&
162+
this.node.inputs.some(
163+
(input)=>
164+
(input.type===BindingType.Property||input.type===BindingType.Attribute)&&
165+
input.name==='type',
166+
);
167+
168+
// If the type is dynamic, check it as if it can be any of the types above.
169+
if(hasDynamicType){
170+
returnts.factory.createUnionTypeNode([
171+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
172+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
173+
ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword),
174+
ts.factory.createTypeReferenceNode('Date'),
175+
ts.factory.createLiteralTypeNode(ts.factory.createNull()),
176+
]);
177+
}
178+
160179
// Fall back to string if we couldn't map the type.
161180
returnts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
162181
}

‎packages/compiler-cli/src/ngtsc/typecheck/test/type_check_block_spec.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2603,6 +2603,22 @@ describe('type check blocks', () => {
26032603
expect(block).toContain('_t2.field = (((this).f));');
26042604
});
26052605

2606+
it('should generate all possible type for input with a dynamic `type`',()=>{
2607+
constblock=tcb('<input [type]="expr" [field]="f"/>',[FieldMock]);
2608+
expect(block).toContain('var _t1 = null! as string | number | boolean | Date | null;');
2609+
expect(block).toContain('_t1 = ((this).f)().value();');
2610+
expect(block).toContain('var _t2 = null! as i0.Field;');
2611+
expect(block).toContain('_t2.field = (((this).f));');
2612+
});
2613+
2614+
it('should generate all possible type for input with a dynamic attribute `type` binding',()=>{
2615+
constblock=tcb('<input [attr.type]="expr" [field]="f"/>',[FieldMock]);
2616+
expect(block).toContain('var _t1 = null! as string | number | boolean | Date | null;');
2617+
expect(block).toContain('_t1 = ((this).f)().value();');
2618+
expect(block).toContain('var _t2 = null! as i0.Field;');
2619+
expect(block).toContain('_t2.field = (((this).f));');
2620+
});
2621+
26062622
[
26072623
{inputType:'text',expectedType:'string'},
26082624
{inputType:'radio',expectedType:'string'},

‎packages/compiler-cli/test/ngtsc/signal_forms_spec.ts‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,5 +601,30 @@ runInEachFileSystem(() => {
601601
constdiags=env.driveDiagnostics();
602602
expect(diags.length).toBe(0);
603603
});
604+
605+
it('should infer an input with a dynamic `type` as being any of the other types',()=>{
606+
env.write(
607+
'test.ts',
608+
`
609+
import {Component, signal} from '@angular/core';
610+
import {Field, form} from '@angular/forms/signals';
611+
612+
@Component({
613+
template: '<input [type]="type" [field]="f"/>',
614+
imports: [Field]
615+
})
616+
export class Comp {
617+
type = '';
618+
f = form(signal({test: true}));
619+
}
620+
`,
621+
);
622+
623+
constdiags=env.driveDiagnostics();
624+
expect(diags.length).toBe(1);
625+
expect(extractMessage(diags[0])).toBe(
626+
`Type '{ test: boolean; }' is not assignable to type 'string | number | boolean | Date | null'.`,
627+
);
628+
});
604629
});
605630
});

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp