mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Add known keys of the mapped type constraint to its members (#50081)
* Add known keys of the mapped type constraint to its members * Avoid second pass of adding known members by instead passing `noReductions` to `mapType`
This commit is contained in:
parent
48aebcdcdb
commit
39ccac654c
@ -12021,7 +12021,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return type;
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return mapType(type as UnionType, getLowerBoundOfKeyType);
|
||||
return mapType(type as UnionType, getLowerBoundOfKeyType, /*noReductions*/ true);
|
||||
}
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
// Similarly to getTypeFromIntersectionTypeNode, we preserve the special string & {}, number & {},
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
tests/cases/compiler/mappedTypeGenericWithKnownKeys.ts(9,9): error TS2551: Property 'unknownLiteralKey' does not exist on type 'Record<keyof Shape | "knownLiteralKey", number>'. Did you mean 'knownLiteralKey'?
|
||||
tests/cases/compiler/mappedTypeGenericWithKnownKeys.ts(10,5): error TS2536: Type 'string' cannot be used to index type 'Record<keyof Shape | "knownLiteralKey", number>'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/mappedTypeGenericWithKnownKeys.ts (2 errors) ====
|
||||
// based on #50054
|
||||
|
||||
function test<Shape extends Record<string, string>>(shape: Shape, key: keyof Shape) {
|
||||
const obj = {} as Record<keyof Shape | "knownLiteralKey", number>;
|
||||
|
||||
obj.knownLiteralKey = 1;
|
||||
obj[key] = 2;
|
||||
|
||||
obj.unknownLiteralKey = 3; // error
|
||||
~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2551: Property 'unknownLiteralKey' does not exist on type 'Record<keyof Shape | "knownLiteralKey", number>'. Did you mean 'knownLiteralKey'?
|
||||
obj['' as string] = 4; // error
|
||||
~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2536: Type 'string' cannot be used to index type 'Record<keyof Shape | "knownLiteralKey", number>'.
|
||||
}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
=== tests/cases/compiler/mappedTypeGenericWithKnownKeys.ts ===
|
||||
// based on #50054
|
||||
|
||||
function test<Shape extends Record<string, string>>(shape: Shape, key: keyof Shape) {
|
||||
>test : Symbol(test, Decl(mappedTypeGenericWithKnownKeys.ts, 0, 0))
|
||||
>Shape : Symbol(Shape, Decl(mappedTypeGenericWithKnownKeys.ts, 2, 14))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>shape : Symbol(shape, Decl(mappedTypeGenericWithKnownKeys.ts, 2, 52))
|
||||
>Shape : Symbol(Shape, Decl(mappedTypeGenericWithKnownKeys.ts, 2, 14))
|
||||
>key : Symbol(key, Decl(mappedTypeGenericWithKnownKeys.ts, 2, 65))
|
||||
>Shape : Symbol(Shape, Decl(mappedTypeGenericWithKnownKeys.ts, 2, 14))
|
||||
|
||||
const obj = {} as Record<keyof Shape | "knownLiteralKey", number>;
|
||||
>obj : Symbol(obj, Decl(mappedTypeGenericWithKnownKeys.ts, 3, 9))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>Shape : Symbol(Shape, Decl(mappedTypeGenericWithKnownKeys.ts, 2, 14))
|
||||
|
||||
obj.knownLiteralKey = 1;
|
||||
>obj.knownLiteralKey : Symbol(knownLiteralKey)
|
||||
>obj : Symbol(obj, Decl(mappedTypeGenericWithKnownKeys.ts, 3, 9))
|
||||
>knownLiteralKey : Symbol(knownLiteralKey)
|
||||
|
||||
obj[key] = 2;
|
||||
>obj : Symbol(obj, Decl(mappedTypeGenericWithKnownKeys.ts, 3, 9))
|
||||
>key : Symbol(key, Decl(mappedTypeGenericWithKnownKeys.ts, 2, 65))
|
||||
|
||||
obj.unknownLiteralKey = 3; // error
|
||||
>obj : Symbol(obj, Decl(mappedTypeGenericWithKnownKeys.ts, 3, 9))
|
||||
|
||||
obj['' as string] = 4; // error
|
||||
>obj : Symbol(obj, Decl(mappedTypeGenericWithKnownKeys.ts, 3, 9))
|
||||
}
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
=== tests/cases/compiler/mappedTypeGenericWithKnownKeys.ts ===
|
||||
// based on #50054
|
||||
|
||||
function test<Shape extends Record<string, string>>(shape: Shape, key: keyof Shape) {
|
||||
>test : <Shape extends Record<string, string>>(shape: Shape, key: keyof Shape) => void
|
||||
>shape : Shape
|
||||
>key : keyof Shape
|
||||
|
||||
const obj = {} as Record<keyof Shape | "knownLiteralKey", number>;
|
||||
>obj : Record<keyof Shape | "knownLiteralKey", number>
|
||||
>{} as Record<keyof Shape | "knownLiteralKey", number> : Record<keyof Shape | "knownLiteralKey", number>
|
||||
>{} : {}
|
||||
|
||||
obj.knownLiteralKey = 1;
|
||||
>obj.knownLiteralKey = 1 : 1
|
||||
>obj.knownLiteralKey : number
|
||||
>obj : Record<keyof Shape | "knownLiteralKey", number>
|
||||
>knownLiteralKey : number
|
||||
>1 : 1
|
||||
|
||||
obj[key] = 2;
|
||||
>obj[key] = 2 : 2
|
||||
>obj[key] : Record<keyof Shape | "knownLiteralKey", number>[keyof Shape]
|
||||
>obj : Record<keyof Shape | "knownLiteralKey", number>
|
||||
>key : keyof Shape
|
||||
>2 : 2
|
||||
|
||||
obj.unknownLiteralKey = 3; // error
|
||||
>obj.unknownLiteralKey = 3 : 3
|
||||
>obj.unknownLiteralKey : any
|
||||
>obj : Record<keyof Shape | "knownLiteralKey", number>
|
||||
>unknownLiteralKey : any
|
||||
>3 : 3
|
||||
|
||||
obj['' as string] = 4; // error
|
||||
>obj['' as string] = 4 : 4
|
||||
>obj['' as string] : any
|
||||
>obj : Record<keyof Shape | "knownLiteralKey", number>
|
||||
>'' as string : string
|
||||
>'' : ""
|
||||
>4 : 4
|
||||
}
|
||||
|
||||
14
tests/cases/compiler/mappedTypeGenericWithKnownKeys.ts
Normal file
14
tests/cases/compiler/mappedTypeGenericWithKnownKeys.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// @noEmit: true
|
||||
// @strict: true
|
||||
|
||||
// based on #50054
|
||||
|
||||
function test<Shape extends Record<string, string>>(shape: Shape, key: keyof Shape) {
|
||||
const obj = {} as Record<keyof Shape | "knownLiteralKey", number>;
|
||||
|
||||
obj.knownLiteralKey = 1;
|
||||
obj[key] = 2;
|
||||
|
||||
obj.unknownLiteralKey = 3; // error
|
||||
obj['' as string] = 4; // error
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user