Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Properly defer resolution of mapped types with generic
as
clauses (#…
…51050) * Fix isGenericMappedType, getTemplateLiteralType, getStringMappingType * Accept new baselines * Add regression tests * Fix comment
- Loading branch information
1 parent
42b1049
commit d06a592
Showing
12 changed files
with
299 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
tests/baselines/reference/genericMappedTypeAsClause.errors.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
tests/cases/compiler/genericMappedTypeAsClause.ts(11,36): error TS2322: Type 'string' is not assignable to type 'number'. | ||
tests/cases/compiler/genericMappedTypeAsClause.ts(14,11): error TS2322: Type 'number' is not assignable to type 'MappedModel<T>'. | ||
tests/cases/compiler/genericMappedTypeAsClause.ts(15,11): error TS2322: Type 'string' is not assignable to type 'MappedModel<T>'. | ||
tests/cases/compiler/genericMappedTypeAsClause.ts(16,11): error TS2322: Type 'number[]' is not assignable to type 'MappedModel<T>'. | ||
tests/cases/compiler/genericMappedTypeAsClause.ts(17,11): error TS2322: Type 'boolean' is not assignable to type 'MappedModel<T>'. | ||
tests/cases/compiler/genericMappedTypeAsClause.ts(18,34): error TS2322: Type '{ a: string; b: number; }' is not assignable to type 'MappedModel<T>'. | ||
Object literal may only specify known properties, and 'a' does not exist in type 'MappedModel<T>'. | ||
tests/cases/compiler/genericMappedTypeAsClause.ts(19,11): error TS2322: Type 'undefined' is not assignable to type 'MappedModel<T>'. | ||
|
||
|
||
==== tests/cases/compiler/genericMappedTypeAsClause.ts (7 errors) ==== | ||
type Model = { | ||
a: string; | ||
b: number; | ||
}; | ||
|
||
type MappedModel<Suffix extends string> = { | ||
[K in keyof Model as `${K}${Suffix}`]: Model[K]; | ||
}; | ||
|
||
const foo1: MappedModel<'Foo'> = { aFoo: 'test', bFoo: 42 }; | ||
const foo2: MappedModel<'Foo'> = { bFoo: 'bar' }; // Error | ||
~~~~ | ||
!!! error TS2322: Type 'string' is not assignable to type 'number'. | ||
!!! related TS6500 tests/cases/compiler/genericMappedTypeAsClause.ts:6:43: The expected type comes from property 'bFoo' which is declared here on type 'MappedModel<"Foo">' | ||
|
||
function f1<T extends string>() { | ||
const x1: MappedModel<T> = 42; // Error | ||
~~ | ||
!!! error TS2322: Type 'number' is not assignable to type 'MappedModel<T>'. | ||
const x2: MappedModel<T> = 'test'; // Error | ||
~~ | ||
!!! error TS2322: Type 'string' is not assignable to type 'MappedModel<T>'. | ||
const x3: MappedModel<T> = [1, 2, 3]; // Error | ||
~~ | ||
!!! error TS2322: Type 'number[]' is not assignable to type 'MappedModel<T>'. | ||
const x4: MappedModel<T> = false; // Error | ||
~~ | ||
!!! error TS2322: Type 'boolean' is not assignable to type 'MappedModel<T>'. | ||
const x5: MappedModel<T> = { a: 'bar', b: 42 }; // Error | ||
~~~~~~~~ | ||
!!! error TS2322: Type '{ a: string; b: number; }' is not assignable to type 'MappedModel<T>'. | ||
!!! error TS2322: Object literal may only specify known properties, and 'a' does not exist in type 'MappedModel<T>'. | ||
const x6: MappedModel<T> = undefined; // Error | ||
~~ | ||
!!! error TS2322: Type 'undefined' is not assignable to type 'MappedModel<T>'. | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
//// [genericMappedTypeAsClause.ts] | ||
type Model = { | ||
a: string; | ||
b: number; | ||
}; | ||
|
||
type MappedModel<Suffix extends string> = { | ||
[K in keyof Model as `${K}${Suffix}`]: Model[K]; | ||
}; | ||
|
||
const foo1: MappedModel<'Foo'> = { aFoo: 'test', bFoo: 42 }; | ||
const foo2: MappedModel<'Foo'> = { bFoo: 'bar' }; // Error | ||
|
||
function f1<T extends string>() { | ||
const x1: MappedModel<T> = 42; // Error | ||
const x2: MappedModel<T> = 'test'; // Error | ||
const x3: MappedModel<T> = [1, 2, 3]; // Error | ||
const x4: MappedModel<T> = false; // Error | ||
const x5: MappedModel<T> = { a: 'bar', b: 42 }; // Error | ||
const x6: MappedModel<T> = undefined; // Error | ||
} | ||
|
||
|
||
//// [genericMappedTypeAsClause.js] | ||
"use strict"; | ||
var foo1 = { aFoo: 'test', bFoo: 42 }; | ||
var foo2 = { bFoo: 'bar' }; // Error | ||
function f1() { | ||
var x1 = 42; // Error | ||
var x2 = 'test'; // Error | ||
var x3 = [1, 2, 3]; // Error | ||
var x4 = false; // Error | ||
var x5 = { a: 'bar', b: 42 }; // Error | ||
var x6 = undefined; // Error | ||
} |
75 changes: 75 additions & 0 deletions
75
tests/baselines/reference/genericMappedTypeAsClause.symbols
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
=== tests/cases/compiler/genericMappedTypeAsClause.ts === | ||
type Model = { | ||
>Model : Symbol(Model, Decl(genericMappedTypeAsClause.ts, 0, 0)) | ||
|
||
a: string; | ||
>a : Symbol(a, Decl(genericMappedTypeAsClause.ts, 0, 14)) | ||
|
||
b: number; | ||
>b : Symbol(b, Decl(genericMappedTypeAsClause.ts, 1, 14)) | ||
|
||
}; | ||
|
||
type MappedModel<Suffix extends string> = { | ||
>MappedModel : Symbol(MappedModel, Decl(genericMappedTypeAsClause.ts, 3, 2)) | ||
>Suffix : Symbol(Suffix, Decl(genericMappedTypeAsClause.ts, 5, 17)) | ||
|
||
[K in keyof Model as `${K}${Suffix}`]: Model[K]; | ||
>K : Symbol(K, Decl(genericMappedTypeAsClause.ts, 6, 5)) | ||
>Model : Symbol(Model, Decl(genericMappedTypeAsClause.ts, 0, 0)) | ||
>K : Symbol(K, Decl(genericMappedTypeAsClause.ts, 6, 5)) | ||
>Suffix : Symbol(Suffix, Decl(genericMappedTypeAsClause.ts, 5, 17)) | ||
>Model : Symbol(Model, Decl(genericMappedTypeAsClause.ts, 0, 0)) | ||
>K : Symbol(K, Decl(genericMappedTypeAsClause.ts, 6, 5)) | ||
|
||
}; | ||
|
||
const foo1: MappedModel<'Foo'> = { aFoo: 'test', bFoo: 42 }; | ||
>foo1 : Symbol(foo1, Decl(genericMappedTypeAsClause.ts, 9, 5)) | ||
>MappedModel : Symbol(MappedModel, Decl(genericMappedTypeAsClause.ts, 3, 2)) | ||
>aFoo : Symbol(aFoo, Decl(genericMappedTypeAsClause.ts, 9, 34)) | ||
>bFoo : Symbol(bFoo, Decl(genericMappedTypeAsClause.ts, 9, 48)) | ||
|
||
const foo2: MappedModel<'Foo'> = { bFoo: 'bar' }; // Error | ||
>foo2 : Symbol(foo2, Decl(genericMappedTypeAsClause.ts, 10, 5)) | ||
>MappedModel : Symbol(MappedModel, Decl(genericMappedTypeAsClause.ts, 3, 2)) | ||
>bFoo : Symbol(bFoo, Decl(genericMappedTypeAsClause.ts, 10, 34)) | ||
|
||
function f1<T extends string>() { | ||
>f1 : Symbol(f1, Decl(genericMappedTypeAsClause.ts, 10, 49)) | ||
>T : Symbol(T, Decl(genericMappedTypeAsClause.ts, 12, 12)) | ||
|
||
const x1: MappedModel<T> = 42; // Error | ||
>x1 : Symbol(x1, Decl(genericMappedTypeAsClause.ts, 13, 9)) | ||
>MappedModel : Symbol(MappedModel, Decl(genericMappedTypeAsClause.ts, 3, 2)) | ||
>T : Symbol(T, Decl(genericMappedTypeAsClause.ts, 12, 12)) | ||
|
||
const x2: MappedModel<T> = 'test'; // Error | ||
>x2 : Symbol(x2, Decl(genericMappedTypeAsClause.ts, 14, 9)) | ||
>MappedModel : Symbol(MappedModel, Decl(genericMappedTypeAsClause.ts, 3, 2)) | ||
>T : Symbol(T, Decl(genericMappedTypeAsClause.ts, 12, 12)) | ||
|
||
const x3: MappedModel<T> = [1, 2, 3]; // Error | ||
>x3 : Symbol(x3, Decl(genericMappedTypeAsClause.ts, 15, 9)) | ||
>MappedModel : Symbol(MappedModel, Decl(genericMappedTypeAsClause.ts, 3, 2)) | ||
>T : Symbol(T, Decl(genericMappedTypeAsClause.ts, 12, 12)) | ||
|
||
const x4: MappedModel<T> = false; // Error | ||
>x4 : Symbol(x4, Decl(genericMappedTypeAsClause.ts, 16, 9)) | ||
>MappedModel : Symbol(MappedModel, Decl(genericMappedTypeAsClause.ts, 3, 2)) | ||
>T : Symbol(T, Decl(genericMappedTypeAsClause.ts, 12, 12)) | ||
|
||
const x5: MappedModel<T> = { a: 'bar', b: 42 }; // Error | ||
>x5 : Symbol(x5, Decl(genericMappedTypeAsClause.ts, 17, 9)) | ||
>MappedModel : Symbol(MappedModel, Decl(genericMappedTypeAsClause.ts, 3, 2)) | ||
>T : Symbol(T, Decl(genericMappedTypeAsClause.ts, 12, 12)) | ||
>a : Symbol(a, Decl(genericMappedTypeAsClause.ts, 17, 32)) | ||
>b : Symbol(b, Decl(genericMappedTypeAsClause.ts, 17, 42)) | ||
|
||
const x6: MappedModel<T> = undefined; // Error | ||
>x6 : Symbol(x6, Decl(genericMappedTypeAsClause.ts, 18, 9)) | ||
>MappedModel : Symbol(MappedModel, Decl(genericMappedTypeAsClause.ts, 3, 2)) | ||
>T : Symbol(T, Decl(genericMappedTypeAsClause.ts, 12, 12)) | ||
>undefined : Symbol(undefined) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
=== tests/cases/compiler/genericMappedTypeAsClause.ts === | ||
type Model = { | ||
>Model : { a: string; b: number; } | ||
|
||
a: string; | ||
>a : string | ||
|
||
b: number; | ||
>b : number | ||
|
||
}; | ||
|
||
type MappedModel<Suffix extends string> = { | ||
>MappedModel : MappedModel<Suffix> | ||
|
||
[K in keyof Model as `${K}${Suffix}`]: Model[K]; | ||
}; | ||
|
||
const foo1: MappedModel<'Foo'> = { aFoo: 'test', bFoo: 42 }; | ||
>foo1 : MappedModel<"Foo"> | ||
>{ aFoo: 'test', bFoo: 42 } : { aFoo: string; bFoo: number; } | ||
>aFoo : string | ||
>'test' : "test" | ||
>bFoo : number | ||
>42 : 42 | ||
|
||
const foo2: MappedModel<'Foo'> = { bFoo: 'bar' }; // Error | ||
>foo2 : MappedModel<"Foo"> | ||
>{ bFoo: 'bar' } : { bFoo: string; } | ||
>bFoo : string | ||
>'bar' : "bar" | ||
|
||
function f1<T extends string>() { | ||
>f1 : <T extends string>() => void | ||
|
||
const x1: MappedModel<T> = 42; // Error | ||
>x1 : MappedModel<T> | ||
>42 : 42 | ||
|
||
const x2: MappedModel<T> = 'test'; // Error | ||
>x2 : MappedModel<T> | ||
>'test' : "test" | ||
|
||
const x3: MappedModel<T> = [1, 2, 3]; // Error | ||
>x3 : MappedModel<T> | ||
>[1, 2, 3] : number[] | ||
>1 : 1 | ||
>2 : 2 | ||
>3 : 3 | ||
|
||
const x4: MappedModel<T> = false; // Error | ||
>x4 : MappedModel<T> | ||
>false : false | ||
|
||
const x5: MappedModel<T> = { a: 'bar', b: 42 }; // Error | ||
>x5 : MappedModel<T> | ||
>{ a: 'bar', b: 42 } : { a: string; b: number; } | ||
>a : string | ||
>'bar' : "bar" | ||
>b : number | ||
>42 : 42 | ||
|
||
const x6: MappedModel<T> = undefined; // Error | ||
>x6 : MappedModel<T> | ||
>undefined : undefined | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.