diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8fa3c4fce2a4a..956978584a567 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15299,7 +15299,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const constraint = getResolvedBaseConstraint(type as InstantiableType | UnionOrIntersectionType); return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined; } - return type.flags & TypeFlags.Index ? stringNumberSymbolType : undefined; + if (type.flags & TypeFlags.Index) { + if (isGenericMappedType((type as IndexType).type)) { + const nameType = getNameTypeFromMappedType((type as IndexType).type as MappedType); + if (nameType) { + return getBaseConstraintOfType(nameType); + } + } + return stringNumberSymbolType; + } + return undefined; } /** @@ -23529,7 +23538,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function getApparentMappedTypeKeys(nameType: Type, targetType: MappedType) { + function getApparentTargetMappedTypeKeys(nameType: Type, targetType: MappedType) { const modifiersType = getApparentType(getModifiersTypeFromMappedType(targetType)); const mappedKeys: Type[] = []; forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType( @@ -23691,6 +23700,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } } + if (sourceFlags & TypeFlags.TypeParameter && source.symbol && some(source.symbol.declarations, d => d.parent.kind === SyntaxKind.MappedType)) { + const constraint = getConstraintOfTypeParameter(source); + if (constraint && isRelatedTo(constraint, target, RecursionFlags.Both, /*reportErrors*/ false) === Ternary.True) { + return Ternary.True; + } + } if (isTupleType(targetType)) { // An index type can have a tuple type target when the tuple type contains variadic elements. // Check if the source is related to the known keys of the tuple type. @@ -23722,7 +23737,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (nameType && isMappedTypeWithKeyofConstraintDeclaration(targetType)) { // we need to get the apparent mappings and union them with the generic mappings, since some properties may be // missing from the `constraintType` which will otherwise be mapped in the object - const mappedKeys = getApparentMappedTypeKeys(nameType, targetType); + const mappedKeys = getApparentTargetMappedTypeKeys(nameType, targetType); // We still need to include the non-apparent (and thus still generic) keys in the target side of the comparison (in case they're in the source side) targetKeys = getUnionType([mappedKeys, nameType]); } @@ -23924,12 +23939,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isDeferredMappedIndex) { const mappedType = (source as IndexType).type as MappedType; const nameType = getNameTypeFromMappedType(mappedType); - // Unlike on the target side, on the source side we do *not* include the generic part of the `nameType`, since that comes from a - // (potentially anonymous) mapped type local type parameter, so that'd never assign outside the mapped type body, but we still want to - // allow assignments of index types of identical (or similar enough) mapped types. - // eg, `keyof {[X in keyof A]: Obj[X]}` should be assignable to `keyof {[Y in keyof A]: Tup[Y]}` because both map over the same set of keys (`keyof A`). - // Without this source-side breakdown, a `keyof {[X in keyof A]: Obj[X]}` style type won't be assignable to anything except itself, which is much too strict. - const sourceMappedKeys = nameType && isMappedTypeWithKeyofConstraintDeclaration(mappedType) ? getApparentMappedTypeKeys(nameType, mappedType) : (nameType || getConstraintTypeFromMappedType(mappedType)); + const sourceMappedKeys = nameType || getConstraintTypeFromMappedType(mappedType); if (result = isRelatedTo(sourceMappedKeys, target, RecursionFlags.Source, reportErrors)) { return result; } @@ -24176,7 +24186,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const sourceConstraint = instantiateType(getConstraintTypeFromMappedType(source), getCombinedMappedTypeOptionality(source) < 0 ? reportUnmeasurableMapper : reportUnreliableMapper); if (result = isRelatedTo(targetConstraint, sourceConstraint, RecursionFlags.Both, reportErrors)) { const mapper = createTypeMapper([getTypeParameterFromMappedType(source)], [getTypeParameterFromMappedType(target)]); - if (instantiateType(getNameTypeFromMappedType(source), mapper) === instantiateType(getNameTypeFromMappedType(target), mapper)) { + if (isTypeIdenticalTo(instantiateType(getNameTypeFromMappedType(source), mapper) ?? unknownType, instantiateType(getNameTypeFromMappedType(target), mapper) ?? unknownType)) { return result & isRelatedTo(instantiateType(getTemplateTypeFromMappedType(source), mapper), getTemplateTypeFromMappedType(target), RecursionFlags.Both, reportErrors); } } diff --git a/tests/baselines/reference/keyRemappingKeyofResult.errors.txt b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt similarity index 62% rename from tests/baselines/reference/keyRemappingKeyofResult.errors.txt rename to tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt index c92c299465e8b..0a1328441d721 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult.errors.txt +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt @@ -1,8 +1,11 @@ keyRemappingKeyofResult.ts(69,5): error TS2322: Type 'string' is not assignable to type 'keyof Remapped'. Type '"whatever"' is not assignable to type 'unique symbol | "str" | DistributiveNonIndex'. +keyRemappingKeyofResult.ts(83,3): error TS2322: Type 'string' is not assignable to type 'Extract'. +keyRemappingKeyofResult.ts(91,3): error TS2322: Type 'string' is not assignable to type 'keyof { [P in keyof T as T[P] extends string ? P : never]: any; }'. + Type 'string' is not assignable to type 'T[P] extends string ? P : never'. -==== keyRemappingKeyofResult.ts (1 errors) ==== +==== keyRemappingKeyofResult.ts (3 errors) ==== const sym = Symbol("") type Orig = { [k: string]: any, str: any, [sym]: any } @@ -25,21 +28,21 @@ keyRemappingKeyofResult.ts(69,5): error TS2322: Type 'string' is not assignable // equivalently, with an unresolved generic (no `exclude` shenanigans, since conditions won't execute): function f() { type Orig = { [k: string]: any, str: any, [sym]: any } & T; - + type Okay = keyof Orig; let a: Okay; a = "str"; a = sym; a = "whatever"; // type Okay = string | number | typeof sym - + type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } /* type Remapped = { str: any; [sym]: any; } */ // no string index signature, right? - + type Oops = keyof Remapped; let x: Oops; x = sym; @@ -49,7 +52,7 @@ keyRemappingKeyofResult.ts(69,5): error TS2322: Type 'string' is not assignable // and another generic case with a _distributive_ mapping, to trigger a different branch in `getIndexType` function g() { type Orig = { [k: string]: any, str: any, [sym]: any } & T; - + type Okay = keyof Orig; let a: Okay; a = "str"; @@ -59,14 +62,14 @@ keyRemappingKeyofResult.ts(69,5): error TS2322: Type 'string' is not assignable type NonIndex = {} extends Record ? never : T; type DistributiveNonIndex = T extends unknown ? NonIndex : never; - + type Remapped = { [K in keyof Orig as DistributiveNonIndex]: any } /* type Remapped = { str: any; [sym]: any; } */ // no string index signature, right? - + type Oops = keyof Remapped; let x: Oops; x = sym; @@ -77,4 +80,33 @@ keyRemappingKeyofResult.ts(69,5): error TS2322: Type 'string' is not assignable !!! error TS2322: Type '"whatever"' is not assignable to type 'unique symbol | "str" | DistributiveNonIndex'. } - export {}; \ No newline at end of file + // https://github.com/microsoft/TypeScript/issues/57827 + + type StringKeys = Extract< + keyof { + [P in keyof T as T[P] extends string ? P : never]: any; + }, + string + >; + + function test_57827(z: StringKeys) { + const f: string = z; + z = "foo"; // error + ~ +!!! error TS2322: Type 'string' is not assignable to type 'Extract'. + } + + type StringKeys2 = keyof { + [P in keyof T as T[P] extends string ? P : never]: any; + }; + + function h(z: StringKeys2) { + z = "foo"; // error + ~ +!!! error TS2322: Type 'string' is not assignable to type 'keyof { [P in keyof T as T[P] extends string ? P : never]: any; }'. +!!! error TS2322: Type 'string' is not assignable to type 'T[P] extends string ? P : never'. + const f: string = z; // ok + } + + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/keyRemappingKeyofResult.js b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).js similarity index 80% rename from tests/baselines/reference/keyRemappingKeyofResult.js rename to tests/baselines/reference/keyRemappingKeyofResult(strict=false).js index 9e4d1ea336c3f..1d6bf38b7c271 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult.js +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).js @@ -23,21 +23,21 @@ x = "str"; // equivalently, with an unresolved generic (no `exclude` shenanigans, since conditions won't execute): function f() { type Orig = { [k: string]: any, str: any, [sym]: any } & T; - + type Okay = keyof Orig; let a: Okay; a = "str"; a = sym; a = "whatever"; // type Okay = string | number | typeof sym - + type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } /* type Remapped = { str: any; [sym]: any; } */ // no string index signature, right? - + type Oops = keyof Remapped; let x: Oops; x = sym; @@ -47,7 +47,7 @@ function f() { // and another generic case with a _distributive_ mapping, to trigger a different branch in `getIndexType` function g() { type Orig = { [k: string]: any, str: any, [sym]: any } & T; - + type Okay = keyof Orig; let a: Okay; a = "str"; @@ -57,14 +57,14 @@ function g() { type NonIndex = {} extends Record ? never : T; type DistributiveNonIndex = T extends unknown ? NonIndex : never; - + type Remapped = { [K in keyof Orig as DistributiveNonIndex]: any } /* type Remapped = { str: any; [sym]: any; } */ // no string index signature, right? - + type Oops = keyof Remapped; let x: Oops; x = sym; @@ -72,7 +72,31 @@ function g() { x = "whatever"; // error } -export {}; +// https://github.com/microsoft/TypeScript/issues/57827 + +type StringKeys = Extract< + keyof { + [P in keyof T as T[P] extends string ? P : never]: any; + }, + string +>; + +function test_57827(z: StringKeys) { + const f: string = z; + z = "foo"; // error +} + +type StringKeys2 = keyof { + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function h(z: StringKeys2) { + z = "foo"; // error + const f: string = z; // ok +} + +export {}; + //// [keyRemappingKeyofResult.js] const sym = Symbol(""); @@ -100,4 +124,12 @@ function g() { x = "str"; x = "whatever"; // error } +function test_57827(z) { + const f = z; + z = "foo"; // error +} +function h(z) { + z = "foo"; // error + const f = z; // ok +} export {}; diff --git a/tests/baselines/reference/keyRemappingKeyofResult.symbols b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols similarity index 75% rename from tests/baselines/reference/keyRemappingKeyofResult.symbols rename to tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols index 3be5cf2460e84..d262ff3c96d2d 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult.symbols +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols @@ -63,7 +63,7 @@ function f() { >[sym] : Symbol([sym], Decl(keyRemappingKeyofResult.ts, 21, 45)) >sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) >T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 20, 11)) - + type Okay = keyof Orig; >Okay : Symbol(Okay, Decl(keyRemappingKeyofResult.ts, 21, 63)) >Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 20, 17)) @@ -83,7 +83,7 @@ function f() { >a : Symbol(a, Decl(keyRemappingKeyofResult.ts, 24, 7)) // type Okay = string | number | typeof sym - + type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } >Remapped : Symbol(Remapped, Decl(keyRemappingKeyofResult.ts, 27, 19)) >K : Symbol(K, Decl(keyRemappingKeyofResult.ts, 30, 23)) @@ -97,7 +97,7 @@ function f() { [sym]: any; } */ // no string index signature, right? - + type Oops = keyof Remapped; >Oops : Symbol(Oops, Decl(keyRemappingKeyofResult.ts, 30, 87)) >Remapped : Symbol(Remapped, Decl(keyRemappingKeyofResult.ts, 27, 19)) @@ -126,7 +126,7 @@ function g() { >[sym] : Symbol([sym], Decl(keyRemappingKeyofResult.ts, 45, 45)) >sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) >T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 44, 11)) - + type Okay = keyof Orig; >Okay : Symbol(Okay, Decl(keyRemappingKeyofResult.ts, 45, 63)) >Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 44, 17)) @@ -162,7 +162,7 @@ function g() { >T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 55, 30)) >NonIndex : Symbol(NonIndex, Decl(keyRemappingKeyofResult.ts, 51, 19)) >T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 55, 30)) - + type Remapped = { [K in keyof Orig as DistributiveNonIndex]: any } >Remapped : Symbol(Remapped, Decl(keyRemappingKeyofResult.ts, 55, 95)) >K : Symbol(K, Decl(keyRemappingKeyofResult.ts, 57, 23)) @@ -175,7 +175,7 @@ function g() { [sym]: any; } */ // no string index signature, right? - + type Oops = keyof Remapped; >Oops : Symbol(Oops, Decl(keyRemappingKeyofResult.ts, 57, 73)) >Remapped : Symbol(Remapped, Decl(keyRemappingKeyofResult.ts, 55, 95)) @@ -195,4 +195,67 @@ function g() { >x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 65, 7)) } +// https://github.com/microsoft/TypeScript/issues/57827 + +type StringKeys = Extract< +>StringKeys : Symbol(StringKeys, Decl(keyRemappingKeyofResult.ts, 69, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 73, 16)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) + + keyof { + [P in keyof T as T[P] extends string ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 75, 5)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 73, 16)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 73, 16)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 75, 5)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 75, 5)) + + }, + string +>; + +function test_57827(z: StringKeys) { +>test_57827 : Symbol(test_57827, Decl(keyRemappingKeyofResult.ts, 78, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 80, 20)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 80, 23)) +>StringKeys : Symbol(StringKeys, Decl(keyRemappingKeyofResult.ts, 69, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 80, 20)) + + const f: string = z; +>f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 81, 7)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 80, 23)) + + z = "foo"; // error +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 80, 23)) +} + +type StringKeys2 = keyof { +>StringKeys2 : Symbol(StringKeys2, Decl(keyRemappingKeyofResult.ts, 83, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 85, 17)) + + [P in keyof T as T[P] extends string ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 86, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 85, 17)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 85, 17)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 86, 3)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 86, 3)) + +}; + +function h(z: StringKeys2) { +>h : Symbol(h, Decl(keyRemappingKeyofResult.ts, 87, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 89, 11)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 89, 14)) +>StringKeys2 : Symbol(StringKeys2, Decl(keyRemappingKeyofResult.ts, 83, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 89, 11)) + + z = "foo"; // error +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 89, 14)) + + const f: string = z; // ok +>f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 91, 7)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 89, 14)) +} + export {}; + diff --git a/tests/baselines/reference/keyRemappingKeyofResult.types b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types similarity index 79% rename from tests/baselines/reference/keyRemappingKeyofResult.types rename to tests/baselines/reference/keyRemappingKeyofResult(strict=false).types index ce371fb30e5de..ebdf7971f7685 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult.types +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types @@ -81,7 +81,7 @@ function f() { > : ^^^ >sym : unique symbol > : ^^^^^^^^^^^^^ - + type Okay = keyof Orig; >Okay : string | number | unique symbol | keyof T > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -115,7 +115,7 @@ function f() { > : ^^^^^^^^^^ // type Okay = string | number | typeof sym - + type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } >Remapped : { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as {} extends Record ? never : K]: any; } > : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -125,7 +125,7 @@ function f() { [sym]: any; } */ // no string index signature, right? - + type Oops = keyof Remapped; >Oops : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as {} extends Record ? never : K]: any; } > : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -167,7 +167,7 @@ function g() { > : ^^^ >sym : unique symbol > : ^^^^^^^^^^^^^ - + type Okay = keyof Orig; >Okay : string | number | unique symbol | keyof T > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ function g() { type DistributiveNonIndex = T extends unknown ? NonIndex : never; >DistributiveNonIndex : T extends unknown ? {} extends Record ? never : T : never > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - + type Remapped = { [K in keyof Orig as DistributiveNonIndex]: any } >Remapped : { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as K extends unknown ? {} extends Record ? never : K : never]: any; } > : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -219,7 +219,7 @@ function g() { [sym]: any; } */ // no string index signature, right? - + type Oops = keyof Remapped; >Oops : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as K extends unknown ? {} extends Record ? never : K : never]: any; } > : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -253,4 +253,66 @@ function g() { > : ^^^^^^^^^^ } +// https://github.com/microsoft/TypeScript/issues/57827 + +type StringKeys = Extract< +>StringKeys : StringKeys +> : ^^^^^^^^^^^^^ + + keyof { + [P in keyof T as T[P] extends string ? P : never]: any; + }, + string +>; + +function test_57827(z: StringKeys) { +>test_57827 : (z: StringKeys) => void +> : ^ ^^ ^^ ^^^^^^^^^ +>z : Extract +> : ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const f: string = z; +>f : string +> : ^^^^^^ +>z : Extract +> : ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + z = "foo"; // error +>z = "foo" : "foo" +> : ^^^^^ +>z : Extract +> : ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"foo" : "foo" +> : ^^^^^ +} + +type StringKeys2 = keyof { +>StringKeys2 : keyof { [P in keyof T as T[P] extends string ? P : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function h(z: StringKeys2) { +>h : (z: StringKeys2) => void +> : ^ ^^ ^^ ^^^^^^^^^ +>z : keyof { [P in keyof T as T[P] extends string ? P : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + z = "foo"; // error +>z = "foo" : "foo" +> : ^^^^^ +>z : keyof { [P in keyof T as T[P] extends string ? P : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + const f: string = z; // ok +>f : string +> : ^^^^^^ +>z : string +> : ^^^^^^ +} + export {}; + diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).errors.txt b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).errors.txt new file mode 100644 index 0000000000000..0a1328441d721 --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).errors.txt @@ -0,0 +1,112 @@ +keyRemappingKeyofResult.ts(69,5): error TS2322: Type 'string' is not assignable to type 'keyof Remapped'. + Type '"whatever"' is not assignable to type 'unique symbol | "str" | DistributiveNonIndex'. +keyRemappingKeyofResult.ts(83,3): error TS2322: Type 'string' is not assignable to type 'Extract'. +keyRemappingKeyofResult.ts(91,3): error TS2322: Type 'string' is not assignable to type 'keyof { [P in keyof T as T[P] extends string ? P : never]: any; }'. + Type 'string' is not assignable to type 'T[P] extends string ? P : never'. + + +==== keyRemappingKeyofResult.ts (3 errors) ==== + const sym = Symbol("") + type Orig = { [k: string]: any, str: any, [sym]: any } + + type Okay = Exclude + // type Okay = string | number | typeof sym + + type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } + /* type Remapped = { + str: any; + [sym]: any; + } */ + // no string index signature, right? + + type Oops = Exclude + declare let x: Oops; + x = sym; + x = "str"; + // type Oops = typeof sym <-- what happened to "str"? + + // equivalently, with an unresolved generic (no `exclude` shenanigans, since conditions won't execute): + function f() { + type Orig = { [k: string]: any, str: any, [sym]: any } & T; + + type Okay = keyof Orig; + let a: Okay; + a = "str"; + a = sym; + a = "whatever"; + // type Okay = string | number | typeof sym + + type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } + /* type Remapped = { + str: any; + [sym]: any; + } */ + // no string index signature, right? + + type Oops = keyof Remapped; + let x: Oops; + x = sym; + x = "str"; + } + + // and another generic case with a _distributive_ mapping, to trigger a different branch in `getIndexType` + function g() { + type Orig = { [k: string]: any, str: any, [sym]: any } & T; + + type Okay = keyof Orig; + let a: Okay; + a = "str"; + a = sym; + a = "whatever"; + // type Okay = string | number | typeof sym + + type NonIndex = {} extends Record ? never : T; + type DistributiveNonIndex = T extends unknown ? NonIndex : never; + + type Remapped = { [K in keyof Orig as DistributiveNonIndex]: any } + /* type Remapped = { + str: any; + [sym]: any; + } */ + // no string index signature, right? + + type Oops = keyof Remapped; + let x: Oops; + x = sym; + x = "str"; + x = "whatever"; // error + ~ +!!! error TS2322: Type 'string' is not assignable to type 'keyof Remapped'. +!!! error TS2322: Type '"whatever"' is not assignable to type 'unique symbol | "str" | DistributiveNonIndex'. + } + + // https://github.com/microsoft/TypeScript/issues/57827 + + type StringKeys = Extract< + keyof { + [P in keyof T as T[P] extends string ? P : never]: any; + }, + string + >; + + function test_57827(z: StringKeys) { + const f: string = z; + z = "foo"; // error + ~ +!!! error TS2322: Type 'string' is not assignable to type 'Extract'. + } + + type StringKeys2 = keyof { + [P in keyof T as T[P] extends string ? P : never]: any; + }; + + function h(z: StringKeys2) { + z = "foo"; // error + ~ +!!! error TS2322: Type 'string' is not assignable to type 'keyof { [P in keyof T as T[P] extends string ? P : never]: any; }'. +!!! error TS2322: Type 'string' is not assignable to type 'T[P] extends string ? P : never'. + const f: string = z; // ok + } + + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js new file mode 100644 index 0000000000000..1d6bf38b7c271 --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js @@ -0,0 +1,135 @@ +//// [tests/cases/compiler/keyRemappingKeyofResult.ts] //// + +//// [keyRemappingKeyofResult.ts] +const sym = Symbol("") +type Orig = { [k: string]: any, str: any, [sym]: any } + +type Okay = Exclude +// type Okay = string | number | typeof sym + +type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } +/* type Remapped = { + str: any; + [sym]: any; +} */ +// no string index signature, right? + +type Oops = Exclude +declare let x: Oops; +x = sym; +x = "str"; +// type Oops = typeof sym <-- what happened to "str"? + +// equivalently, with an unresolved generic (no `exclude` shenanigans, since conditions won't execute): +function f() { + type Orig = { [k: string]: any, str: any, [sym]: any } & T; + + type Okay = keyof Orig; + let a: Okay; + a = "str"; + a = sym; + a = "whatever"; + // type Okay = string | number | typeof sym + + type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } + /* type Remapped = { + str: any; + [sym]: any; + } */ + // no string index signature, right? + + type Oops = keyof Remapped; + let x: Oops; + x = sym; + x = "str"; +} + +// and another generic case with a _distributive_ mapping, to trigger a different branch in `getIndexType` +function g() { + type Orig = { [k: string]: any, str: any, [sym]: any } & T; + + type Okay = keyof Orig; + let a: Okay; + a = "str"; + a = sym; + a = "whatever"; + // type Okay = string | number | typeof sym + + type NonIndex = {} extends Record ? never : T; + type DistributiveNonIndex = T extends unknown ? NonIndex : never; + + type Remapped = { [K in keyof Orig as DistributiveNonIndex]: any } + /* type Remapped = { + str: any; + [sym]: any; + } */ + // no string index signature, right? + + type Oops = keyof Remapped; + let x: Oops; + x = sym; + x = "str"; + x = "whatever"; // error +} + +// https://github.com/microsoft/TypeScript/issues/57827 + +type StringKeys = Extract< + keyof { + [P in keyof T as T[P] extends string ? P : never]: any; + }, + string +>; + +function test_57827(z: StringKeys) { + const f: string = z; + z = "foo"; // error +} + +type StringKeys2 = keyof { + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function h(z: StringKeys2) { + z = "foo"; // error + const f: string = z; // ok +} + +export {}; + + +//// [keyRemappingKeyofResult.js] +const sym = Symbol(""); +x = sym; +x = "str"; +// type Oops = typeof sym <-- what happened to "str"? +// equivalently, with an unresolved generic (no `exclude` shenanigans, since conditions won't execute): +function f() { + let a; + a = "str"; + a = sym; + a = "whatever"; + let x; + x = sym; + x = "str"; +} +// and another generic case with a _distributive_ mapping, to trigger a different branch in `getIndexType` +function g() { + let a; + a = "str"; + a = sym; + a = "whatever"; + let x; + x = sym; + x = "str"; + x = "whatever"; // error +} +function test_57827(z) { + const f = z; + z = "foo"; // error +} +function h(z) { + z = "foo"; // error + const f = z; // ok +} +export {}; diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).symbols b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).symbols new file mode 100644 index 0000000000000..d262ff3c96d2d --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).symbols @@ -0,0 +1,261 @@ +//// [tests/cases/compiler/keyRemappingKeyofResult.ts] //// + +=== keyRemappingKeyofResult.ts === +const sym = Symbol("") +>sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +type Orig = { [k: string]: any, str: any, [sym]: any } +>Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 0, 22)) +>k : Symbol(k, Decl(keyRemappingKeyofResult.ts, 1, 15)) +>str : Symbol(str, Decl(keyRemappingKeyofResult.ts, 1, 31)) +>[sym] : Symbol([sym], Decl(keyRemappingKeyofResult.ts, 1, 41)) +>sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) + +type Okay = Exclude +>Okay : Symbol(Okay, Decl(keyRemappingKeyofResult.ts, 1, 54)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 0, 22)) + +// type Okay = string | number | typeof sym + +type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } +>Remapped : Symbol(Remapped, Decl(keyRemappingKeyofResult.ts, 3, 38)) +>K : Symbol(K, Decl(keyRemappingKeyofResult.ts, 6, 19)) +>Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 0, 22)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>K : Symbol(K, Decl(keyRemappingKeyofResult.ts, 6, 19)) +>K : Symbol(K, Decl(keyRemappingKeyofResult.ts, 6, 19)) + +/* type Remapped = { + str: any; + [sym]: any; +} */ +// no string index signature, right? + +type Oops = Exclude +>Oops : Symbol(Oops, Decl(keyRemappingKeyofResult.ts, 6, 83)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>Remapped : Symbol(Remapped, Decl(keyRemappingKeyofResult.ts, 3, 38)) + +declare let x: Oops; +>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 14, 11)) +>Oops : Symbol(Oops, Decl(keyRemappingKeyofResult.ts, 6, 83)) + +x = sym; +>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 14, 11)) +>sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) + +x = "str"; +>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 14, 11)) + +// type Oops = typeof sym <-- what happened to "str"? + +// equivalently, with an unresolved generic (no `exclude` shenanigans, since conditions won't execute): +function f() { +>f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 16, 10)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 20, 11)) + + type Orig = { [k: string]: any, str: any, [sym]: any } & T; +>Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 20, 17)) +>k : Symbol(k, Decl(keyRemappingKeyofResult.ts, 21, 19)) +>str : Symbol(str, Decl(keyRemappingKeyofResult.ts, 21, 35)) +>[sym] : Symbol([sym], Decl(keyRemappingKeyofResult.ts, 21, 45)) +>sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 20, 11)) + + type Okay = keyof Orig; +>Okay : Symbol(Okay, Decl(keyRemappingKeyofResult.ts, 21, 63)) +>Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 20, 17)) + + let a: Okay; +>a : Symbol(a, Decl(keyRemappingKeyofResult.ts, 24, 7)) +>Okay : Symbol(Okay, Decl(keyRemappingKeyofResult.ts, 21, 63)) + + a = "str"; +>a : Symbol(a, Decl(keyRemappingKeyofResult.ts, 24, 7)) + + a = sym; +>a : Symbol(a, Decl(keyRemappingKeyofResult.ts, 24, 7)) +>sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) + + a = "whatever"; +>a : Symbol(a, Decl(keyRemappingKeyofResult.ts, 24, 7)) + + // type Okay = string | number | typeof sym + + type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } +>Remapped : Symbol(Remapped, Decl(keyRemappingKeyofResult.ts, 27, 19)) +>K : Symbol(K, Decl(keyRemappingKeyofResult.ts, 30, 23)) +>Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 20, 17)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>K : Symbol(K, Decl(keyRemappingKeyofResult.ts, 30, 23)) +>K : Symbol(K, Decl(keyRemappingKeyofResult.ts, 30, 23)) + + /* type Remapped = { + str: any; + [sym]: any; + } */ + // no string index signature, right? + + type Oops = keyof Remapped; +>Oops : Symbol(Oops, Decl(keyRemappingKeyofResult.ts, 30, 87)) +>Remapped : Symbol(Remapped, Decl(keyRemappingKeyofResult.ts, 27, 19)) + + let x: Oops; +>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 38, 7)) +>Oops : Symbol(Oops, Decl(keyRemappingKeyofResult.ts, 30, 87)) + + x = sym; +>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 38, 7)) +>sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) + + x = "str"; +>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 38, 7)) +} + +// and another generic case with a _distributive_ mapping, to trigger a different branch in `getIndexType` +function g() { +>g : Symbol(g, Decl(keyRemappingKeyofResult.ts, 41, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 44, 11)) + + type Orig = { [k: string]: any, str: any, [sym]: any } & T; +>Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 44, 17)) +>k : Symbol(k, Decl(keyRemappingKeyofResult.ts, 45, 19)) +>str : Symbol(str, Decl(keyRemappingKeyofResult.ts, 45, 35)) +>[sym] : Symbol([sym], Decl(keyRemappingKeyofResult.ts, 45, 45)) +>sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 44, 11)) + + type Okay = keyof Orig; +>Okay : Symbol(Okay, Decl(keyRemappingKeyofResult.ts, 45, 63)) +>Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 44, 17)) + + let a: Okay; +>a : Symbol(a, Decl(keyRemappingKeyofResult.ts, 48, 7)) +>Okay : Symbol(Okay, Decl(keyRemappingKeyofResult.ts, 45, 63)) + + a = "str"; +>a : Symbol(a, Decl(keyRemappingKeyofResult.ts, 48, 7)) + + a = sym; +>a : Symbol(a, Decl(keyRemappingKeyofResult.ts, 48, 7)) +>sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) + + a = "whatever"; +>a : Symbol(a, Decl(keyRemappingKeyofResult.ts, 48, 7)) + + // type Okay = string | number | typeof sym + + type NonIndex = {} extends Record ? never : T; +>NonIndex : Symbol(NonIndex, Decl(keyRemappingKeyofResult.ts, 51, 19)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 54, 18)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 54, 18)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 54, 18)) + + type DistributiveNonIndex = T extends unknown ? NonIndex : never; +>DistributiveNonIndex : Symbol(DistributiveNonIndex, Decl(keyRemappingKeyofResult.ts, 54, 81)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 55, 30)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 55, 30)) +>NonIndex : Symbol(NonIndex, Decl(keyRemappingKeyofResult.ts, 51, 19)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 55, 30)) + + type Remapped = { [K in keyof Orig as DistributiveNonIndex]: any } +>Remapped : Symbol(Remapped, Decl(keyRemappingKeyofResult.ts, 55, 95)) +>K : Symbol(K, Decl(keyRemappingKeyofResult.ts, 57, 23)) +>Orig : Symbol(Orig, Decl(keyRemappingKeyofResult.ts, 44, 17)) +>DistributiveNonIndex : Symbol(DistributiveNonIndex, Decl(keyRemappingKeyofResult.ts, 54, 81)) +>K : Symbol(K, Decl(keyRemappingKeyofResult.ts, 57, 23)) + + /* type Remapped = { + str: any; + [sym]: any; + } */ + // no string index signature, right? + + type Oops = keyof Remapped; +>Oops : Symbol(Oops, Decl(keyRemappingKeyofResult.ts, 57, 73)) +>Remapped : Symbol(Remapped, Decl(keyRemappingKeyofResult.ts, 55, 95)) + + let x: Oops; +>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 65, 7)) +>Oops : Symbol(Oops, Decl(keyRemappingKeyofResult.ts, 57, 73)) + + x = sym; +>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 65, 7)) +>sym : Symbol(sym, Decl(keyRemappingKeyofResult.ts, 0, 5)) + + x = "str"; +>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 65, 7)) + + x = "whatever"; // error +>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 65, 7)) +} + +// https://github.com/microsoft/TypeScript/issues/57827 + +type StringKeys = Extract< +>StringKeys : Symbol(StringKeys, Decl(keyRemappingKeyofResult.ts, 69, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 73, 16)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) + + keyof { + [P in keyof T as T[P] extends string ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 75, 5)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 73, 16)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 73, 16)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 75, 5)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 75, 5)) + + }, + string +>; + +function test_57827(z: StringKeys) { +>test_57827 : Symbol(test_57827, Decl(keyRemappingKeyofResult.ts, 78, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 80, 20)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 80, 23)) +>StringKeys : Symbol(StringKeys, Decl(keyRemappingKeyofResult.ts, 69, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 80, 20)) + + const f: string = z; +>f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 81, 7)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 80, 23)) + + z = "foo"; // error +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 80, 23)) +} + +type StringKeys2 = keyof { +>StringKeys2 : Symbol(StringKeys2, Decl(keyRemappingKeyofResult.ts, 83, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 85, 17)) + + [P in keyof T as T[P] extends string ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 86, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 85, 17)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 85, 17)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 86, 3)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 86, 3)) + +}; + +function h(z: StringKeys2) { +>h : Symbol(h, Decl(keyRemappingKeyofResult.ts, 87, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 89, 11)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 89, 14)) +>StringKeys2 : Symbol(StringKeys2, Decl(keyRemappingKeyofResult.ts, 83, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 89, 11)) + + z = "foo"; // error +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 89, 14)) + + const f: string = z; // ok +>f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 91, 7)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 89, 14)) +} + +export {}; + diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types new file mode 100644 index 0000000000000..ebdf7971f7685 --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types @@ -0,0 +1,318 @@ +//// [tests/cases/compiler/keyRemappingKeyofResult.ts] //// + +=== keyRemappingKeyofResult.ts === +const sym = Symbol("") +>sym : unique symbol +> : ^^^^^^^^^^^^^ +>Symbol("") : unique symbol +> : ^^^^^^^^^^^^^ +>Symbol : SymbolConstructor +> : ^^^^^^^^^^^^^^^^^ +>"" : "" +> : ^^ + +type Orig = { [k: string]: any, str: any, [sym]: any } +>Orig : Orig +> : ^^^^ +>k : string +> : ^^^^^^ +>str : any +> : ^^^ +>[sym] : any +> : ^^^ +>sym : unique symbol +> : ^^^^^^^^^^^^^ + +type Okay = Exclude +>Okay : Okay +> : ^^^^ + +// type Okay = string | number | typeof sym + +type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } +>Remapped : Remapped +> : ^^^^^^^^ + +/* type Remapped = { + str: any; + [sym]: any; +} */ +// no string index signature, right? + +type Oops = Exclude +>Oops : Oops +> : ^^^^ + +declare let x: Oops; +>x : Oops +> : ^^^^ + +x = sym; +>x = sym : unique symbol +> : ^^^^^^^^^^^^^ +>x : Oops +> : ^^^^ +>sym : unique symbol +> : ^^^^^^^^^^^^^ + +x = "str"; +>x = "str" : "str" +> : ^^^^^ +>x : Oops +> : ^^^^ +>"str" : "str" +> : ^^^^^ + +// type Oops = typeof sym <-- what happened to "str"? + +// equivalently, with an unresolved generic (no `exclude` shenanigans, since conditions won't execute): +function f() { +>f : () => void +> : ^ ^^^^^^^^^^^ + + type Orig = { [k: string]: any, str: any, [sym]: any } & T; +>Orig : { [k: string]: any; str: any; [sym]: any; } & T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^ +>k : string +> : ^^^^^^ +>str : any +> : ^^^ +>[sym] : any +> : ^^^ +>sym : unique symbol +> : ^^^^^^^^^^^^^ + + type Okay = keyof Orig; +>Okay : string | number | unique symbol | keyof T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + let a: Okay; +>a : string | number | unique symbol | keyof T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + a = "str"; +>a = "str" : "str" +> : ^^^^^ +>a : string | number | unique symbol | keyof T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"str" : "str" +> : ^^^^^ + + a = sym; +>a = sym : unique symbol +> : ^^^^^^^^^^^^^ +>a : string | number | unique symbol | keyof T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>sym : unique symbol +> : ^^^^^^^^^^^^^ + + a = "whatever"; +>a = "whatever" : "whatever" +> : ^^^^^^^^^^ +>a : string | number | unique symbol | keyof T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"whatever" : "whatever" +> : ^^^^^^^^^^ + + // type Okay = string | number | typeof sym + + type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } +>Remapped : { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as {} extends Record ? never : K]: any; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + /* type Remapped = { + str: any; + [sym]: any; + } */ + // no string index signature, right? + + type Oops = keyof Remapped; +>Oops : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as {} extends Record ? never : K]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + let x: Oops; +>x : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as {} extends Record ? never : K]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + x = sym; +>x = sym : unique symbol +> : ^^^^^^^^^^^^^ +>x : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as {} extends Record ? never : K]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>sym : unique symbol +> : ^^^^^^^^^^^^^ + + x = "str"; +>x = "str" : "str" +> : ^^^^^ +>x : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as {} extends Record ? never : K]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"str" : "str" +> : ^^^^^ +} + +// and another generic case with a _distributive_ mapping, to trigger a different branch in `getIndexType` +function g() { +>g : () => void +> : ^ ^^^^^^^^^^^ + + type Orig = { [k: string]: any, str: any, [sym]: any } & T; +>Orig : { [k: string]: any; str: any; [sym]: any; } & T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^ +>k : string +> : ^^^^^^ +>str : any +> : ^^^ +>[sym] : any +> : ^^^ +>sym : unique symbol +> : ^^^^^^^^^^^^^ + + type Okay = keyof Orig; +>Okay : string | number | unique symbol | keyof T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + let a: Okay; +>a : string | number | unique symbol | keyof T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + a = "str"; +>a = "str" : "str" +> : ^^^^^ +>a : string | number | unique symbol | keyof T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"str" : "str" +> : ^^^^^ + + a = sym; +>a = sym : unique symbol +> : ^^^^^^^^^^^^^ +>a : string | number | unique symbol | keyof T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>sym : unique symbol +> : ^^^^^^^^^^^^^ + + a = "whatever"; +>a = "whatever" : "whatever" +> : ^^^^^^^^^^ +>a : string | number | unique symbol | keyof T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"whatever" : "whatever" +> : ^^^^^^^^^^ + + // type Okay = string | number | typeof sym + + type NonIndex = {} extends Record ? never : T; +>NonIndex : {} extends Record ? never : T +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type DistributiveNonIndex = T extends unknown ? NonIndex : never; +>DistributiveNonIndex : T extends unknown ? {} extends Record ? never : T : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type Remapped = { [K in keyof Orig as DistributiveNonIndex]: any } +>Remapped : { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as K extends unknown ? {} extends Record ? never : K : never]: any; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + /* type Remapped = { + str: any; + [sym]: any; + } */ + // no string index signature, right? + + type Oops = keyof Remapped; +>Oops : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as K extends unknown ? {} extends Record ? never : K : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + let x: Oops; +>x : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as K extends unknown ? {} extends Record ? never : K : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + x = sym; +>x = sym : unique symbol +> : ^^^^^^^^^^^^^ +>x : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as K extends unknown ? {} extends Record ? never : K : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>sym : unique symbol +> : ^^^^^^^^^^^^^ + + x = "str"; +>x = "str" : "str" +> : ^^^^^ +>x : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as K extends unknown ? {} extends Record ? never : K : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"str" : "str" +> : ^^^^^ + + x = "whatever"; // error +>x = "whatever" : "whatever" +> : ^^^^^^^^^^ +>x : keyof { [K in keyof ({ [k: string]: any; str: any; [sym]: any; } & T) as K extends unknown ? {} extends Record ? never : K : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"whatever" : "whatever" +> : ^^^^^^^^^^ +} + +// https://github.com/microsoft/TypeScript/issues/57827 + +type StringKeys = Extract< +>StringKeys : StringKeys +> : ^^^^^^^^^^^^^ + + keyof { + [P in keyof T as T[P] extends string ? P : never]: any; + }, + string +>; + +function test_57827(z: StringKeys) { +>test_57827 : (z: StringKeys) => void +> : ^ ^^ ^^ ^^^^^^^^^ +>z : Extract +> : ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const f: string = z; +>f : string +> : ^^^^^^ +>z : Extract +> : ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + z = "foo"; // error +>z = "foo" : "foo" +> : ^^^^^ +>z : Extract +> : ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"foo" : "foo" +> : ^^^^^ +} + +type StringKeys2 = keyof { +>StringKeys2 : keyof { [P in keyof T as T[P] extends string ? P : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function h(z: StringKeys2) { +>h : (z: StringKeys2) => void +> : ^ ^^ ^^ ^^^^^^^^^ +>z : keyof { [P in keyof T as T[P] extends string ? P : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + z = "foo"; // error +>z = "foo" : "foo" +> : ^^^^^ +>z : keyof { [P in keyof T as T[P] extends string ? P : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + const f: string = z; // ok +>f : string +> : ^^^^^^ +>z : string +> : ^^^^^^ +} + +export {}; + diff --git a/tests/baselines/reference/keyRemappingKeyofResult3.errors.txt b/tests/baselines/reference/keyRemappingKeyofResult3.errors.txt new file mode 100644 index 0000000000000..31f01c5549ae0 --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult3.errors.txt @@ -0,0 +1,489 @@ +keyRemappingKeyofResult3.ts(9,9): error TS2322: Type 'keyof Prefixed1' is not assignable to type '"pre_a"'. + Type '`pre_${K & string}`' is not assignable to type '"pre_a"'. + Type '`pre_${string}`' is not assignable to type '"pre_a"'. +keyRemappingKeyofResult3.ts(24,9): error TS2322: Type '`p_${K}`' is not assignable to type '"p_a" | "p_b"'. + Type '`p_${string}`' is not assignable to type '"p_a" | "p_b"'. +keyRemappingKeyofResult3.ts(32,9): error TS2322: Type '"p_a" | "p_b"' is not assignable to type '"p_a"'. + Type '"p_b"' is not assignable to type '"p_a"'. +keyRemappingKeyofResult3.ts(66,9): error TS2322: Type 'keyof Constrained1' is not assignable to type '"c_a" | "c_b"'. + Type '`c_${K & string}`' is not assignable to type '"c_a" | "c_b"'. + Type '`c_${string}`' is not assignable to type '"c_a" | "c_b"'. +keyRemappingKeyofResult3.ts(87,9): error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(88,30): error TS2344: Type 'keyof StringPropsOnly' does not satisfy the constraint 'string'. + Type 'T[P] extends string ? P : never' is not assignable to type 'string'. + Type 'P' is not assignable to type 'string'. + Type 'keyof T' is not assignable to type 'string'. + Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(101,9): error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(102,30): error TS2344: Type 'keyof FilterByLiteralValue' does not satisfy the constraint 'string'. + Type 'T[P] extends 1 ? P : never' is not assignable to type 'string'. + Type 'P' is not assignable to type 'string'. + Type 'keyof T' is not assignable to type 'string'. + Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(112,9): error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(113,9): error TS2322: Type 'string | number | symbol' is not assignable to type '"x"'. + Type 'string' is not assignable to type '"x"'. +keyRemappingKeyofResult3.ts(114,31): error TS2344: Type 'keyof FilterByStringValue' does not satisfy the constraint 'string'. + Type 'T[P] extends string ? P : never' is not assignable to type 'string'. + Type 'P' is not assignable to type 'string'. + Type 'keyof T' is not assignable to type 'string'. + Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(115,27): error TS2344: Type 'keyof FilterByStringValue' does not satisfy the constraint '"a" | "b"'. + Type 'T[P] extends string ? P : never' is not assignable to type '"a" | "b"'. + Type 'P' is not assignable to type '"a" | "b"'. + Type 'keyof T' is not assignable to type '"a" | "b"'. + Type 'string | number | symbol' is not assignable to type '"a" | "b"'. + Type 'string' is not assignable to type '"a" | "b"'. +keyRemappingKeyofResult3.ts(116,26): error TS2344: Type 'keyof FilterByStringValue' does not satisfy the constraint '"a"'. + Type 'T[P] extends string ? P : never' is not assignable to type '"a"'. + Type 'P' is not assignable to type '"a"'. + Type 'keyof T' is not assignable to type '"a"'. + Type 'string | number | symbol' is not assignable to type '"a"'. + Type 'string' is not assignable to type '"a"'. +keyRemappingKeyofResult3.ts(141,9): error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(142,9): error TS2322: Type 'string' is not assignable to type 'keyof PickByType'. + Type '"a"' is not assignable to type '(T[P] extends string ? P : never) | (T["a"] extends string ? "a" : never) | (T["b"] extends string ? "b" : never)'. +keyRemappingKeyofResult3.ts(143,9): error TS2322: Type 'string | number | symbol' is not assignable to type '"a"'. + Type 'string' is not assignable to type '"a"'. +keyRemappingKeyofResult3.ts(145,30): error TS2344: Type 'keyof PickByType' does not satisfy the constraint 'string'. + Type 'T[P] extends string ? P : never' is not assignable to type 'string'. + Type 'P' is not assignable to type 'string'. + Type 'keyof T' is not assignable to type 'string'. + Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(146,27): error TS2344: Type 'keyof PickByType' does not satisfy the constraint '"a" | "b"'. + Type 'T[P] extends string ? P : never' is not assignable to type '"a" | "b"'. + Type 'P' is not assignable to type '"a" | "b"'. + Type 'keyof T' is not assignable to type '"a" | "b"'. + Type 'string | number | symbol' is not assignable to type '"a" | "b"'. + Type 'string' is not assignable to type '"a" | "b"'. +keyRemappingKeyofResult3.ts(147,26): error TS2344: Type 'keyof PickByType' does not satisfy the constraint '"a"'. + Type 'T[P] extends string ? P : never' is not assignable to type '"a"'. + Type 'P' is not assignable to type '"a"'. + Type 'keyof T' is not assignable to type '"a"'. + Type 'string | number | symbol' is not assignable to type '"a"'. + Type 'string' is not assignable to type '"a"'. +keyRemappingKeyofResult3.ts(153,30): error TS2344: Type 'keyof { [P in keyof T as T[P] extends string ? P : never]: any; }' does not satisfy the constraint 'string'. + Type 'T[P] extends string ? P : never' is not assignable to type 'string'. + Type 'P' is not assignable to type 'string'. + Type 'keyof T' is not assignable to type 'string'. + Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(182,9): error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(183,9): error TS2322: Type 'string | number | symbol' is not assignable to type '"a"'. + Type 'string' is not assignable to type '"a"'. +keyRemappingKeyofResult3.ts(184,9): error TS2322: Type 'string | number | symbol' is not assignable to type '"a" | "b"'. + Type 'string' is not assignable to type '"a" | "b"'. +keyRemappingKeyofResult3.ts(185,30): error TS2344: Type 'keyof StringPropsOnly' does not satisfy the constraint 'string'. + Type 'T[P] extends string ? P : never' is not assignable to type 'string'. + Type 'P' is not assignable to type 'string'. + Type 'keyof T' is not assignable to type 'string'. + Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(186,27): error TS2344: Type 'keyof StringPropsOnly' does not satisfy the constraint '"a" | "b"'. + Type 'T[P] extends string ? P : never' is not assignable to type '"a" | "b"'. + Type 'P' is not assignable to type '"a" | "b"'. + Type 'keyof T' is not assignable to type '"a" | "b"'. + Type 'string | number | symbol' is not assignable to type '"a" | "b"'. + Type 'string' is not assignable to type '"a" | "b"'. +keyRemappingKeyofResult3.ts(187,26): error TS2344: Type 'keyof StringPropsOnly' does not satisfy the constraint '"a"'. + Type 'T[P] extends string ? P : never' is not assignable to type '"a"'. + Type 'P' is not assignable to type '"a"'. + Type 'keyof T' is not assignable to type '"a"'. + Type 'string | number | symbol' is not assignable to type '"a"'. + Type 'string' is not assignable to type '"a"'. +keyRemappingKeyofResult3.ts(195,9): error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(196,9): error TS2322: Type 'string | number | symbol' is not assignable to type '"a"'. + Type 'string' is not assignable to type '"a"'. +keyRemappingKeyofResult3.ts(197,9): error TS2322: Type 'string | number | symbol' is not assignable to type '"a" | "b"'. + Type 'string' is not assignable to type '"a" | "b"'. +keyRemappingKeyofResult3.ts(198,30): error TS2344: Type 'keyof ValueIs1' does not satisfy the constraint 'string'. + Type 'T[P] extends 1 ? P : never' is not assignable to type 'string'. + Type 'P' is not assignable to type 'string'. + Type 'keyof T' is not assignable to type 'string'. + Type 'string | number | symbol' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +keyRemappingKeyofResult3.ts(199,27): error TS2344: Type 'keyof ValueIs1' does not satisfy the constraint '"a" | "b"'. + Type 'T[P] extends 1 ? P : never' is not assignable to type '"a" | "b"'. + Type 'P' is not assignable to type '"a" | "b"'. + Type 'keyof T' is not assignable to type '"a" | "b"'. + Type 'string | number | symbol' is not assignable to type '"a" | "b"'. + Type 'string' is not assignable to type '"a" | "b"'. +keyRemappingKeyofResult3.ts(200,26): error TS2344: Type 'keyof ValueIs1' does not satisfy the constraint '"a"'. + Type 'T[P] extends 1 ? P : never' is not assignable to type '"a"'. + Type 'P' is not assignable to type '"a"'. + Type 'keyof T' is not assignable to type '"a"'. + Type 'string | number | symbol' is not assignable to type '"a"'. + Type 'string' is not assignable to type '"a"'. + + +==== keyRemappingKeyofResult3.ts (32 errors) ==== + type AcceptA = T; + type AcceptAB = T; + type AcceptString = T; + + type Prefixed1 = { [K in keyof T as `pre_${K & string}`]: T[K] }; + + function test1(k: keyof Prefixed1) { + const a: `pre_${string}` = k; // ok + const b: `pre_a` | `pre_a` = k; // error + ~ +!!! error TS2322: Type 'keyof Prefixed1' is not assignable to type '"pre_a"'. +!!! error TS2322: Type '`pre_${K & string}`' is not assignable to type '"pre_a"'. +!!! error TS2322: Type '`pre_${string}`' is not assignable to type '"pre_a"'. + } + + type RemapA = { [K in keyof T as `x_${K & string}`]: T[K] }; + type RemapB = { [K in keyof T as `x_${K & string}`]: number }; + + function test2(ka: keyof RemapA, kb: keyof RemapB) { + let a: keyof RemapA = kb; // ok + let b: keyof RemapB = ka; // ok + } + + type Prefixed2 = { [P in K as `p_${P}`]: any }; + + function test3(k: keyof Prefixed2) { + const a: `p_${string}` = k; // ok + const b: `p_a` | `p_b` = k; // error + ~ +!!! error TS2322: Type '`p_${K}`' is not assignable to type '"p_a" | "p_b"'. +!!! error TS2322: Type '`p_${string}`' is not assignable to type '"p_a" | "p_b"'. + } + + type Prefixed3 = { [P in K as `p_${P}`]: any }; + + function test4(k: keyof Prefixed2) { + const a: `p_${string}` = k; // ok + const b: `p_a` | `p_b` = k; // ok + const c: `p_a` = k; // error + ~ +!!! error TS2322: Type '"p_a" | "p_b"' is not assignable to type '"p_a"'. +!!! error TS2322: Type '"p_b"' is not assignable to type '"p_a"'. + } + + type OmitMapped = { + [K in keyof T as Exclude]: T[K]; + }; + + function test5(k: keyof OmitMapped) { + const x: Exclude = k; // ok + } + + type Uppercased = { [K in keyof T as Uppercase]: T[K] }; + + function test6(k: keyof Uppercased) { + const a: Uppercase = k; // ok + } + + type Base1 = { a: 1; b: 2 }; + type Constrained1 = { + [K in keyof T as `c_${K & string}`]: T[K]; + }; + type Constrained2 = { + [K in keyof T as `c_${K & string}`]: boolean; + }; + + function test7( + k1: keyof Constrained1, + k2: keyof Constrained2, + ) { + let a: keyof Constrained1 = k2; // ok + let b: keyof Constrained2 = k1; // ok + } + + function test8(k: keyof Constrained1) { + const a: "c_a" | "c_b" = k; // error + ~ +!!! error TS2322: Type 'keyof Constrained1' is not assignable to type '"c_a" | "c_b"'. +!!! error TS2322: Type '`c_${K & string}`' is not assignable to type '"c_a" | "c_b"'. +!!! error TS2322: Type '`c_${string}`' is not assignable to type '"c_a" | "c_b"'. + const b: `c_${string}` = k; // ok + } + + type StringPropsOnly = { + [P in keyof T as T[P] extends string ? P : never]: any; + }; + + function test9(k: Extract, string>) { + const s: string = k; // ok + type Result = AcceptString; // ok + } + + type AllKeysMapped = { [P in keyof T as P]: any }; + + function test10(k: Extract, string>) { + const s: string = k; // ok + type Result = AcceptString; // ok + } + + function test11(k: keyof StringPropsOnly) { + const s: string = k; // error + ~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + type Result = AcceptString; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof StringPropsOnly' does not satisfy the constraint 'string'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type 'string'. +!!! error TS2344: Type 'P' is not assignable to type 'string'. +!!! error TS2344: Type 'keyof T' is not assignable to type 'string'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2344: Type 'number' is not assignable to type 'string'. + } + + function test12(k: string & keyof StringPropsOnly) { + const s: string = k; // ok + type Result = AcceptString; // ok + } + + type FilterByLiteralValue = { + [P in keyof T as T[P] extends V ? P : never]: any; + }; + + function test13(k: keyof FilterByLiteralValue) { + const s: string = k; // error + ~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + type Result = AcceptString; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof FilterByLiteralValue' does not satisfy the constraint 'string'. +!!! error TS2344: Type 'T[P] extends 1 ? P : never' is not assignable to type 'string'. +!!! error TS2344: Type 'P' is not assignable to type 'string'. +!!! error TS2344: Type 'keyof T' is not assignable to type 'string'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2344: Type 'number' is not assignable to type 'string'. + } + + type Base2 = { x: string; y: number }; + + type FilterByStringValue = { + [P in keyof T as T[P] extends string ? P : never]: any; + }; + + function test14(k: keyof FilterByStringValue) { + const s: string = k; // error + ~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + const s2: "x" = k; // error + ~~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type '"x"'. +!!! error TS2322: Type 'string' is not assignable to type '"x"'. + type Result1 = AcceptString; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof FilterByStringValue' does not satisfy the constraint 'string'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type 'string'. +!!! error TS2344: Type 'P' is not assignable to type 'string'. +!!! error TS2344: Type 'keyof T' is not assignable to type 'string'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2344: Type 'number' is not assignable to type 'string'. + type Result2 = AcceptAB; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof FilterByStringValue' does not satisfy the constraint '"a" | "b"'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'P' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'keyof T' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'string' is not assignable to type '"a" | "b"'. + type Result3 = AcceptA; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof FilterByStringValue' does not satisfy the constraint '"a"'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type '"a"'. +!!! error TS2344: Type 'P' is not assignable to type '"a"'. +!!! error TS2344: Type 'keyof T' is not assignable to type '"a"'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type '"a"'. +!!! error TS2344: Type 'string' is not assignable to type '"a"'. + } + + type RemapC = { [P in keyof T as T[P] extends string ? P : never]: T[P] }; + type RemapD = { [P in keyof T as T[P] extends string ? P : never]: number }; + + function test15(ka: keyof RemapC, kb: keyof RemapD) { + let a: keyof RemapC = kb; // ok + let b: keyof RemapD = ka; // ok + } + + type Base3 = { a: string; b: string; c: string }; + + type AlwaysNever = { [P in keyof T as 1 extends string ? P : never]: any }; + + function test16(k: keyof AlwaysNever) { + const s: string = k; // ok + type Result = AcceptString; // ok + } + + type Base4 = { a: string; b: number }; + + type PickByType = { [P in keyof T as T[P] extends V ? P : never]: T[P] }; + + function test17(k: keyof PickByType) { + const s: string = k; // error + ~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + const s2: typeof k = "a"; // error (checks against a deferred conditional type) + ~~ +!!! error TS2322: Type 'string' is not assignable to type 'keyof PickByType'. +!!! error TS2322: Type '"a"' is not assignable to type '(T[P] extends string ? P : never) | (T["a"] extends string ? "a" : never) | (T["b"] extends string ? "b" : never)'. + const s3: "a" = k; // error + ~~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type '"a"'. +!!! error TS2322: Type 'string' is not assignable to type '"a"'. + + type Result = AcceptString; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof PickByType' does not satisfy the constraint 'string'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type 'string'. +!!! error TS2344: Type 'P' is not assignable to type 'string'. +!!! error TS2344: Type 'keyof T' is not assignable to type 'string'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2344: Type 'number' is not assignable to type 'string'. + type Result2 = AcceptAB; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof PickByType' does not satisfy the constraint '"a" | "b"'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'P' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'keyof T' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'string' is not assignable to type '"a" | "b"'. + type Result3 = AcceptA; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof PickByType' does not satisfy the constraint '"a"'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type '"a"'. +!!! error TS2344: Type 'P' is not assignable to type '"a"'. +!!! error TS2344: Type 'keyof T' is not assignable to type '"a"'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type '"a"'. +!!! error TS2344: Type 'string' is not assignable to type '"a"'. + } + + function test18(o: { + [P in keyof T as T[P] extends string ? P : never]: any; + }) { + type Result = AcceptString; // error + ~~~~~~~~~~~~~~ +!!! error TS2344: Type 'keyof { [P in keyof T as T[P] extends string ? P : never]: any; }' does not satisfy the constraint 'string'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type 'string'. +!!! error TS2344: Type 'P' is not assignable to type 'string'. +!!! error TS2344: Type 'keyof T' is not assignable to type 'string'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2344: Type 'number' is not assignable to type 'string'. + } + + type Inner = { [P in keyof T as P extends string ? P : never]: T[P] }; + type Outer = { + [P in keyof Inner as P extends `a${string}` ? P : never]: any; + }; + + function test19( + k: keyof Outer, + ) { + const s: string = k; // ok + type Result = AcceptString; // ok + } + + type Prefixed4 = { + [P in keyof T as P extends string ? `mapped_${P}` : never]: any; + }; + + function test20( + k: keyof Prefixed4, + ) { + const s: string = k; // ok + type Result = AcceptString; // ok + } + + type Base5 = { a: string; b: number | string }; + + function test21(k: keyof StringPropsOnly) { + const s: string = k; // error + ~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + const s1: "a" = k; // error + ~~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type '"a"'. +!!! error TS2322: Type 'string' is not assignable to type '"a"'. + const s2: "a" | "b" = k; // error + ~~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type '"a" | "b"'. +!!! error TS2322: Type 'string' is not assignable to type '"a" | "b"'. + type Result = AcceptString; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof StringPropsOnly' does not satisfy the constraint 'string'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type 'string'. +!!! error TS2344: Type 'P' is not assignable to type 'string'. +!!! error TS2344: Type 'keyof T' is not assignable to type 'string'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2344: Type 'number' is not assignable to type 'string'. + type Result2 = AcceptAB; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof StringPropsOnly' does not satisfy the constraint '"a" | "b"'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'P' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'keyof T' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'string' is not assignable to type '"a" | "b"'. + type Result3 = AcceptA; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof StringPropsOnly' does not satisfy the constraint '"a"'. +!!! error TS2344: Type 'T[P] extends string ? P : never' is not assignable to type '"a"'. +!!! error TS2344: Type 'P' is not assignable to type '"a"'. +!!! error TS2344: Type 'keyof T' is not assignable to type '"a"'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type '"a"'. +!!! error TS2344: Type 'string' is not assignable to type '"a"'. + } + + type ValueIs1 = { [P in keyof T as T[P] extends 1 ? P : never]: any }; + + type Base6 = { [key: string]: number; a: 1 }; + + function test22(k: keyof ValueIs1) { + const s: string = k; // error + ~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + const s1: "a" = k; // error + ~~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type '"a"'. +!!! error TS2322: Type 'string' is not assignable to type '"a"'. + const s2: "a" | "b" = k; // error + ~~ +!!! error TS2322: Type 'string | number | symbol' is not assignable to type '"a" | "b"'. +!!! error TS2322: Type 'string' is not assignable to type '"a" | "b"'. + type Result = AcceptString; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof ValueIs1' does not satisfy the constraint 'string'. +!!! error TS2344: Type 'T[P] extends 1 ? P : never' is not assignable to type 'string'. +!!! error TS2344: Type 'P' is not assignable to type 'string'. +!!! error TS2344: Type 'keyof T' is not assignable to type 'string'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type 'string'. +!!! error TS2344: Type 'number' is not assignable to type 'string'. + type Result2 = AcceptAB; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof ValueIs1' does not satisfy the constraint '"a" | "b"'. +!!! error TS2344: Type 'T[P] extends 1 ? P : never' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'P' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'keyof T' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type '"a" | "b"'. +!!! error TS2344: Type 'string' is not assignable to type '"a" | "b"'. + type Result3 = AcceptA; // error + ~~~~~~~~ +!!! error TS2344: Type 'keyof ValueIs1' does not satisfy the constraint '"a"'. +!!! error TS2344: Type 'T[P] extends 1 ? P : never' is not assignable to type '"a"'. +!!! error TS2344: Type 'P' is not assignable to type '"a"'. +!!! error TS2344: Type 'keyof T' is not assignable to type '"a"'. +!!! error TS2344: Type 'string | number | symbol' is not assignable to type '"a"'. +!!! error TS2344: Type 'string' is not assignable to type '"a"'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/keyRemappingKeyofResult3.symbols b/tests/baselines/reference/keyRemappingKeyofResult3.symbols new file mode 100644 index 0000000000000..2fda0e024d1cf --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult3.symbols @@ -0,0 +1,760 @@ +//// [tests/cases/compiler/keyRemappingKeyofResult3.ts] //// + +=== keyRemappingKeyofResult3.ts === +type AcceptA = T; +>AcceptA : Symbol(AcceptA, Decl(keyRemappingKeyofResult3.ts, 0, 0)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 0, 13)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 0, 13)) + +type AcceptAB = T; +>AcceptAB : Symbol(AcceptAB, Decl(keyRemappingKeyofResult3.ts, 0, 32)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 1, 14)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 1, 14)) + +type AcceptString = T; +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 2, 18)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 2, 18)) + +type Prefixed1 = { [K in keyof T as `pre_${K & string}`]: T[K] }; +>Prefixed1 : Symbol(Prefixed1, Decl(keyRemappingKeyofResult3.ts, 2, 40)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 4, 15)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 4, 23)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 4, 15)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 4, 23)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 4, 15)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 4, 23)) + +function test1(k: keyof Prefixed1) { +>test1 : Symbol(test1, Decl(keyRemappingKeyofResult3.ts, 4, 68)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 6, 15)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 6, 18)) +>Prefixed1 : Symbol(Prefixed1, Decl(keyRemappingKeyofResult3.ts, 2, 40)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 6, 15)) + + const a: `pre_${string}` = k; // ok +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 7, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 6, 18)) + + const b: `pre_a` | `pre_a` = k; // error +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 8, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 6, 18)) +} + +type RemapA = { [K in keyof T as `x_${K & string}`]: T[K] }; +>RemapA : Symbol(RemapA, Decl(keyRemappingKeyofResult3.ts, 9, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 11, 12)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 11, 20)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 11, 12)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 11, 20)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 11, 12)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 11, 20)) + +type RemapB = { [K in keyof T as `x_${K & string}`]: number }; +>RemapB : Symbol(RemapB, Decl(keyRemappingKeyofResult3.ts, 11, 63)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 12, 12)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 12, 20)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 12, 12)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 12, 20)) + +function test2(ka: keyof RemapA, kb: keyof RemapB) { +>test2 : Symbol(test2, Decl(keyRemappingKeyofResult3.ts, 12, 65)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 14, 15)) +>ka : Symbol(ka, Decl(keyRemappingKeyofResult3.ts, 14, 18)) +>RemapA : Symbol(RemapA, Decl(keyRemappingKeyofResult3.ts, 9, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 14, 15)) +>kb : Symbol(kb, Decl(keyRemappingKeyofResult3.ts, 14, 38)) +>RemapB : Symbol(RemapB, Decl(keyRemappingKeyofResult3.ts, 11, 63)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 14, 15)) + + let a: keyof RemapA = kb; // ok +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 15, 5)) +>RemapA : Symbol(RemapA, Decl(keyRemappingKeyofResult3.ts, 9, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 14, 15)) +>kb : Symbol(kb, Decl(keyRemappingKeyofResult3.ts, 14, 38)) + + let b: keyof RemapB = ka; // ok +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 16, 5)) +>RemapB : Symbol(RemapB, Decl(keyRemappingKeyofResult3.ts, 11, 63)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 14, 15)) +>ka : Symbol(ka, Decl(keyRemappingKeyofResult3.ts, 14, 18)) +} + +type Prefixed2 = { [P in K as `p_${P}`]: any }; +>Prefixed2 : Symbol(Prefixed2, Decl(keyRemappingKeyofResult3.ts, 17, 1)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 19, 15)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 19, 38)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 19, 15)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 19, 38)) + +function test3(k: keyof Prefixed2) { +>test3 : Symbol(test3, Decl(keyRemappingKeyofResult3.ts, 19, 65)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 21, 15)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 21, 33)) +>Prefixed2 : Symbol(Prefixed2, Decl(keyRemappingKeyofResult3.ts, 17, 1)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 21, 15)) + + const a: `p_${string}` = k; // ok +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 22, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 21, 33)) + + const b: `p_a` | `p_b` = k; // error +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 23, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 21, 33)) +} + +type Prefixed3 = { [P in K as `p_${P}`]: any }; +>Prefixed3 : Symbol(Prefixed3, Decl(keyRemappingKeyofResult3.ts, 24, 1)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 26, 15)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 26, 38)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 26, 15)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 26, 38)) + +function test4(k: keyof Prefixed2) { +>test4 : Symbol(test4, Decl(keyRemappingKeyofResult3.ts, 26, 65)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 28, 15)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 28, 36)) +>Prefixed2 : Symbol(Prefixed2, Decl(keyRemappingKeyofResult3.ts, 17, 1)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 28, 15)) + + const a: `p_${string}` = k; // ok +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 29, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 28, 36)) + + const b: `p_a` | `p_b` = k; // ok +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 30, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 28, 36)) + + const c: `p_a` = k; // error +>c : Symbol(c, Decl(keyRemappingKeyofResult3.ts, 31, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 28, 36)) +} + +type OmitMapped = { +>OmitMapped : Symbol(OmitMapped, Decl(keyRemappingKeyofResult3.ts, 32, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 34, 16)) +>E : Symbol(E, Decl(keyRemappingKeyofResult3.ts, 34, 18)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 34, 16)) + + [K in keyof T as Exclude]: T[K]; +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 35, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 34, 16)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 35, 3)) +>E : Symbol(E, Decl(keyRemappingKeyofResult3.ts, 34, 18)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 34, 16)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 35, 3)) + +}; + +function test5(k: keyof OmitMapped) { +>test5 : Symbol(test5, Decl(keyRemappingKeyofResult3.ts, 36, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 38, 15)) +>E : Symbol(E, Decl(keyRemappingKeyofResult3.ts, 38, 17)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 38, 15)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 38, 37)) +>OmitMapped : Symbol(OmitMapped, Decl(keyRemappingKeyofResult3.ts, 32, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 38, 15)) +>E : Symbol(E, Decl(keyRemappingKeyofResult3.ts, 38, 17)) + + const x: Exclude = k; // ok +>x : Symbol(x, Decl(keyRemappingKeyofResult3.ts, 39, 7)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 38, 15)) +>E : Symbol(E, Decl(keyRemappingKeyofResult3.ts, 38, 17)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 38, 37)) +} + +type Uppercased = { [K in keyof T as Uppercase]: T[K] }; +>Uppercased : Symbol(Uppercased, Decl(keyRemappingKeyofResult3.ts, 40, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 42, 16)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 42, 24)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 42, 16)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 42, 24)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 42, 16)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 42, 24)) + +function test6(k: keyof Uppercased) { +>test6 : Symbol(test6, Decl(keyRemappingKeyofResult3.ts, 42, 71)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 44, 15)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 44, 18)) +>Uppercased : Symbol(Uppercased, Decl(keyRemappingKeyofResult3.ts, 40, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 44, 15)) + + const a: Uppercase = k; // ok +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 45, 7)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 44, 18)) +} + +type Base1 = { a: 1; b: 2 }; +>Base1 : Symbol(Base1, Decl(keyRemappingKeyofResult3.ts, 46, 1)) +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 48, 14)) +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 48, 20)) + +type Constrained1 = { +>Constrained1 : Symbol(Constrained1, Decl(keyRemappingKeyofResult3.ts, 48, 28)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 49, 18)) +>Base1 : Symbol(Base1, Decl(keyRemappingKeyofResult3.ts, 46, 1)) + + [K in keyof T as `c_${K & string}`]: T[K]; +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 50, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 49, 18)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 50, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 49, 18)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 50, 3)) + +}; +type Constrained2 = { +>Constrained2 : Symbol(Constrained2, Decl(keyRemappingKeyofResult3.ts, 51, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 52, 18)) +>Base1 : Symbol(Base1, Decl(keyRemappingKeyofResult3.ts, 46, 1)) + + [K in keyof T as `c_${K & string}`]: boolean; +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 53, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 52, 18)) +>K : Symbol(K, Decl(keyRemappingKeyofResult3.ts, 53, 3)) + +}; + +function test7( +>test7 : Symbol(test7, Decl(keyRemappingKeyofResult3.ts, 54, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 56, 15)) +>Base1 : Symbol(Base1, Decl(keyRemappingKeyofResult3.ts, 46, 1)) + + k1: keyof Constrained1, +>k1 : Symbol(k1, Decl(keyRemappingKeyofResult3.ts, 56, 32)) +>Constrained1 : Symbol(Constrained1, Decl(keyRemappingKeyofResult3.ts, 48, 28)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 56, 15)) + + k2: keyof Constrained2, +>k2 : Symbol(k2, Decl(keyRemappingKeyofResult3.ts, 57, 28)) +>Constrained2 : Symbol(Constrained2, Decl(keyRemappingKeyofResult3.ts, 51, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 56, 15)) + +) { + let a: keyof Constrained1 = k2; // ok +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 60, 5)) +>Constrained1 : Symbol(Constrained1, Decl(keyRemappingKeyofResult3.ts, 48, 28)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 56, 15)) +>k2 : Symbol(k2, Decl(keyRemappingKeyofResult3.ts, 57, 28)) + + let b: keyof Constrained2 = k1; // ok +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 61, 5)) +>Constrained2 : Symbol(Constrained2, Decl(keyRemappingKeyofResult3.ts, 51, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 56, 15)) +>k1 : Symbol(k1, Decl(keyRemappingKeyofResult3.ts, 56, 32)) +} + +function test8(k: keyof Constrained1) { +>test8 : Symbol(test8, Decl(keyRemappingKeyofResult3.ts, 62, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 64, 15)) +>Base1 : Symbol(Base1, Decl(keyRemappingKeyofResult3.ts, 46, 1)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 64, 32)) +>Constrained1 : Symbol(Constrained1, Decl(keyRemappingKeyofResult3.ts, 48, 28)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 64, 15)) + + const a: "c_a" | "c_b" = k; // error +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 65, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 64, 32)) + + const b: `c_${string}` = k; // ok +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 66, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 64, 32)) +} + +type StringPropsOnly = { +>StringPropsOnly : Symbol(StringPropsOnly, Decl(keyRemappingKeyofResult3.ts, 67, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 69, 21)) + + [P in keyof T as T[P] extends string ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 70, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 69, 21)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 69, 21)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 70, 3)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 70, 3)) + +}; + +function test9(k: Extract, string>) { +>test9 : Symbol(test9, Decl(keyRemappingKeyofResult3.ts, 71, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 73, 15)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 73, 18)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>StringPropsOnly : Symbol(StringPropsOnly, Decl(keyRemappingKeyofResult3.ts, 67, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 73, 15)) + + const s: string = k; // ok +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 74, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 73, 18)) + + type Result = AcceptString; // ok +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 74, 22)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 73, 18)) +} + +type AllKeysMapped = { [P in keyof T as P]: any }; +>AllKeysMapped : Symbol(AllKeysMapped, Decl(keyRemappingKeyofResult3.ts, 76, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 78, 19)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 78, 27)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 78, 19)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 78, 27)) + +function test10(k: Extract, string>) { +>test10 : Symbol(test10, Decl(keyRemappingKeyofResult3.ts, 78, 53)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 80, 16)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 80, 19)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>AllKeysMapped : Symbol(AllKeysMapped, Decl(keyRemappingKeyofResult3.ts, 76, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 80, 16)) + + const s: string = k; // ok +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 81, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 80, 19)) + + type Result = AcceptString; // ok +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 81, 22)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 80, 19)) +} + +function test11(k: keyof StringPropsOnly) { +>test11 : Symbol(test11, Decl(keyRemappingKeyofResult3.ts, 83, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 85, 16)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 85, 19)) +>StringPropsOnly : Symbol(StringPropsOnly, Decl(keyRemappingKeyofResult3.ts, 67, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 85, 16)) + + const s: string = k; // error +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 86, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 85, 19)) + + type Result = AcceptString; // error +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 86, 22)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 85, 19)) +} + +function test12(k: string & keyof StringPropsOnly) { +>test12 : Symbol(test12, Decl(keyRemappingKeyofResult3.ts, 88, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 90, 16)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 90, 19)) +>StringPropsOnly : Symbol(StringPropsOnly, Decl(keyRemappingKeyofResult3.ts, 67, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 90, 16)) + + const s: string = k; // ok +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 91, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 90, 19)) + + type Result = AcceptString; // ok +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 91, 22)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 90, 19)) +} + +type FilterByLiteralValue = { +>FilterByLiteralValue : Symbol(FilterByLiteralValue, Decl(keyRemappingKeyofResult3.ts, 93, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 95, 26)) +>V : Symbol(V, Decl(keyRemappingKeyofResult3.ts, 95, 28)) + + [P in keyof T as T[P] extends V ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 96, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 95, 26)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 95, 26)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 96, 3)) +>V : Symbol(V, Decl(keyRemappingKeyofResult3.ts, 95, 28)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 96, 3)) + +}; + +function test13(k: keyof FilterByLiteralValue) { +>test13 : Symbol(test13, Decl(keyRemappingKeyofResult3.ts, 97, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 99, 16)) +>Base1 : Symbol(Base1, Decl(keyRemappingKeyofResult3.ts, 46, 1)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 99, 33)) +>FilterByLiteralValue : Symbol(FilterByLiteralValue, Decl(keyRemappingKeyofResult3.ts, 93, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 99, 16)) + + const s: string = k; // error +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 100, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 99, 33)) + + type Result = AcceptString; // error +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 100, 22)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 99, 33)) +} + +type Base2 = { x: string; y: number }; +>Base2 : Symbol(Base2, Decl(keyRemappingKeyofResult3.ts, 102, 1)) +>x : Symbol(x, Decl(keyRemappingKeyofResult3.ts, 104, 14)) +>y : Symbol(y, Decl(keyRemappingKeyofResult3.ts, 104, 25)) + +type FilterByStringValue = { +>FilterByStringValue : Symbol(FilterByStringValue, Decl(keyRemappingKeyofResult3.ts, 104, 38)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 106, 25)) + + [P in keyof T as T[P] extends string ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 107, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 106, 25)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 106, 25)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 107, 3)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 107, 3)) + +}; + +function test14(k: keyof FilterByStringValue) { +>test14 : Symbol(test14, Decl(keyRemappingKeyofResult3.ts, 108, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 110, 16)) +>Base2 : Symbol(Base2, Decl(keyRemappingKeyofResult3.ts, 102, 1)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 110, 33)) +>FilterByStringValue : Symbol(FilterByStringValue, Decl(keyRemappingKeyofResult3.ts, 104, 38)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 110, 16)) + + const s: string = k; // error +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 111, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 110, 33)) + + const s2: "x" = k; // error +>s2 : Symbol(s2, Decl(keyRemappingKeyofResult3.ts, 112, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 110, 33)) + + type Result1 = AcceptString; // error +>Result1 : Symbol(Result1, Decl(keyRemappingKeyofResult3.ts, 112, 20)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 110, 33)) + + type Result2 = AcceptAB; // error +>Result2 : Symbol(Result2, Decl(keyRemappingKeyofResult3.ts, 113, 40)) +>AcceptAB : Symbol(AcceptAB, Decl(keyRemappingKeyofResult3.ts, 0, 32)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 110, 33)) + + type Result3 = AcceptA; // error +>Result3 : Symbol(Result3, Decl(keyRemappingKeyofResult3.ts, 114, 36)) +>AcceptA : Symbol(AcceptA, Decl(keyRemappingKeyofResult3.ts, 0, 0)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 110, 33)) +} + +type RemapC = { [P in keyof T as T[P] extends string ? P : never]: T[P] }; +>RemapC : Symbol(RemapC, Decl(keyRemappingKeyofResult3.ts, 116, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 118, 12)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 118, 20)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 118, 12)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 118, 12)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 118, 20)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 118, 20)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 118, 12)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 118, 20)) + +type RemapD = { [P in keyof T as T[P] extends string ? P : never]: number }; +>RemapD : Symbol(RemapD, Decl(keyRemappingKeyofResult3.ts, 118, 77)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 119, 12)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 119, 20)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 119, 12)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 119, 12)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 119, 20)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 119, 20)) + +function test15(ka: keyof RemapC, kb: keyof RemapD) { +>test15 : Symbol(test15, Decl(keyRemappingKeyofResult3.ts, 119, 79)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 121, 16)) +>Base2 : Symbol(Base2, Decl(keyRemappingKeyofResult3.ts, 102, 1)) +>ka : Symbol(ka, Decl(keyRemappingKeyofResult3.ts, 121, 33)) +>RemapC : Symbol(RemapC, Decl(keyRemappingKeyofResult3.ts, 116, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 121, 16)) +>kb : Symbol(kb, Decl(keyRemappingKeyofResult3.ts, 121, 53)) +>RemapD : Symbol(RemapD, Decl(keyRemappingKeyofResult3.ts, 118, 77)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 121, 16)) + + let a: keyof RemapC = kb; // ok +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 122, 5)) +>RemapC : Symbol(RemapC, Decl(keyRemappingKeyofResult3.ts, 116, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 121, 16)) +>kb : Symbol(kb, Decl(keyRemappingKeyofResult3.ts, 121, 53)) + + let b: keyof RemapD = ka; // ok +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 123, 5)) +>RemapD : Symbol(RemapD, Decl(keyRemappingKeyofResult3.ts, 118, 77)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 121, 16)) +>ka : Symbol(ka, Decl(keyRemappingKeyofResult3.ts, 121, 33)) +} + +type Base3 = { a: string; b: string; c: string }; +>Base3 : Symbol(Base3, Decl(keyRemappingKeyofResult3.ts, 124, 1)) +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 126, 14)) +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 126, 25)) +>c : Symbol(c, Decl(keyRemappingKeyofResult3.ts, 126, 36)) + +type AlwaysNever = { [P in keyof T as 1 extends string ? P : never]: any }; +>AlwaysNever : Symbol(AlwaysNever, Decl(keyRemappingKeyofResult3.ts, 126, 49)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 128, 17)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 128, 25)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 128, 17)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 128, 25)) + +function test16(k: keyof AlwaysNever) { +>test16 : Symbol(test16, Decl(keyRemappingKeyofResult3.ts, 128, 78)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 130, 16)) +>Base3 : Symbol(Base3, Decl(keyRemappingKeyofResult3.ts, 124, 1)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 130, 33)) +>AlwaysNever : Symbol(AlwaysNever, Decl(keyRemappingKeyofResult3.ts, 126, 49)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 130, 16)) + + const s: string = k; // ok +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 131, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 130, 33)) + + type Result = AcceptString; // ok +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 131, 22)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 130, 33)) +} + +type Base4 = { a: string; b: number }; +>Base4 : Symbol(Base4, Decl(keyRemappingKeyofResult3.ts, 133, 1)) +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 135, 14)) +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 135, 25)) + +type PickByType = { [P in keyof T as T[P] extends V ? P : never]: T[P] }; +>PickByType : Symbol(PickByType, Decl(keyRemappingKeyofResult3.ts, 135, 38)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 137, 16)) +>V : Symbol(V, Decl(keyRemappingKeyofResult3.ts, 137, 18)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 137, 27)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 137, 16)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 137, 16)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 137, 27)) +>V : Symbol(V, Decl(keyRemappingKeyofResult3.ts, 137, 18)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 137, 27)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 137, 16)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 137, 27)) + +function test17(k: keyof PickByType) { +>test17 : Symbol(test17, Decl(keyRemappingKeyofResult3.ts, 137, 79)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 139, 16)) +>Base4 : Symbol(Base4, Decl(keyRemappingKeyofResult3.ts, 133, 1)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 139, 33)) +>PickByType : Symbol(PickByType, Decl(keyRemappingKeyofResult3.ts, 135, 38)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 139, 16)) + + const s: string = k; // error +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 140, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 139, 33)) + + const s2: typeof k = "a"; // error (checks against a deferred conditional type) +>s2 : Symbol(s2, Decl(keyRemappingKeyofResult3.ts, 141, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 139, 33)) + + const s3: "a" = k; // error +>s3 : Symbol(s3, Decl(keyRemappingKeyofResult3.ts, 142, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 139, 33)) + + type Result = AcceptString; // error +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 142, 20)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 139, 33)) + + type Result2 = AcceptAB; // error +>Result2 : Symbol(Result2, Decl(keyRemappingKeyofResult3.ts, 144, 39)) +>AcceptAB : Symbol(AcceptAB, Decl(keyRemappingKeyofResult3.ts, 0, 32)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 139, 33)) + + type Result3 = AcceptA; // error +>Result3 : Symbol(Result3, Decl(keyRemappingKeyofResult3.ts, 145, 36)) +>AcceptA : Symbol(AcceptA, Decl(keyRemappingKeyofResult3.ts, 0, 0)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 139, 33)) +} + +function test18(o: { +>test18 : Symbol(test18, Decl(keyRemappingKeyofResult3.ts, 147, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 149, 16)) +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 149, 27)) +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 149, 38)) +>o : Symbol(o, Decl(keyRemappingKeyofResult3.ts, 149, 52)) + + [P in keyof T as T[P] extends string ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 150, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 149, 16)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 149, 16)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 150, 3)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 150, 3)) + +}) { + type Result = AcceptString; // error +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 151, 4)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>o : Symbol(o, Decl(keyRemappingKeyofResult3.ts, 149, 52)) +} + +type Inner = { [P in keyof T as P extends string ? P : never]: T[P] }; +>Inner : Symbol(Inner, Decl(keyRemappingKeyofResult3.ts, 153, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 155, 11)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 155, 19)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 155, 11)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 155, 19)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 155, 19)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 155, 11)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 155, 19)) + +type Outer = { +>Outer : Symbol(Outer, Decl(keyRemappingKeyofResult3.ts, 155, 73)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 156, 11)) + + [P in keyof Inner as P extends `a${string}` ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 157, 3)) +>Inner : Symbol(Inner, Decl(keyRemappingKeyofResult3.ts, 153, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 156, 11)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 157, 3)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 157, 3)) + +}; + +function test19( +>test19 : Symbol(test19, Decl(keyRemappingKeyofResult3.ts, 158, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 160, 16)) +>apple : Symbol(apple, Decl(keyRemappingKeyofResult3.ts, 160, 27)) +>apricot : Symbol(apricot, Decl(keyRemappingKeyofResult3.ts, 160, 37)) +>banana : Symbol(banana, Decl(keyRemappingKeyofResult3.ts, 160, 49)) + + k: keyof Outer, +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 160, 63)) +>Outer : Symbol(Outer, Decl(keyRemappingKeyofResult3.ts, 155, 73)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 160, 16)) + +) { + const s: string = k; // ok +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 163, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 160, 63)) + + type Result = AcceptString; // ok +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 163, 22)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 160, 63)) +} + +type Prefixed4 = { +>Prefixed4 : Symbol(Prefixed4, Decl(keyRemappingKeyofResult3.ts, 165, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 167, 15)) + + [P in keyof T as P extends string ? `mapped_${P}` : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 168, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 167, 15)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 168, 3)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 168, 3)) + +}; + +function test20( +>test20 : Symbol(test20, Decl(keyRemappingKeyofResult3.ts, 169, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 171, 16)) +>key : Symbol(key, Decl(keyRemappingKeyofResult3.ts, 171, 29)) +>specific : Symbol(specific, Decl(keyRemappingKeyofResult3.ts, 171, 50)) + + k: keyof Prefixed4, +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 171, 66)) +>Prefixed4 : Symbol(Prefixed4, Decl(keyRemappingKeyofResult3.ts, 165, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 171, 16)) + +) { + const s: string = k; // ok +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 174, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 171, 66)) + + type Result = AcceptString; // ok +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 174, 22)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 171, 66)) +} + +type Base5 = { a: string; b: number | string }; +>Base5 : Symbol(Base5, Decl(keyRemappingKeyofResult3.ts, 176, 1)) +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 178, 14)) +>b : Symbol(b, Decl(keyRemappingKeyofResult3.ts, 178, 25)) + +function test21(k: keyof StringPropsOnly) { +>test21 : Symbol(test21, Decl(keyRemappingKeyofResult3.ts, 178, 47)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 180, 16)) +>Base5 : Symbol(Base5, Decl(keyRemappingKeyofResult3.ts, 176, 1)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 180, 33)) +>StringPropsOnly : Symbol(StringPropsOnly, Decl(keyRemappingKeyofResult3.ts, 67, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 180, 16)) + + const s: string = k; // error +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 181, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 180, 33)) + + const s1: "a" = k; // error +>s1 : Symbol(s1, Decl(keyRemappingKeyofResult3.ts, 182, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 180, 33)) + + const s2: "a" | "b" = k; // error +>s2 : Symbol(s2, Decl(keyRemappingKeyofResult3.ts, 183, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 180, 33)) + + type Result = AcceptString; // error +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 183, 26)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 180, 33)) + + type Result2 = AcceptAB; // error +>Result2 : Symbol(Result2, Decl(keyRemappingKeyofResult3.ts, 184, 39)) +>AcceptAB : Symbol(AcceptAB, Decl(keyRemappingKeyofResult3.ts, 0, 32)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 180, 33)) + + type Result3 = AcceptA; // error +>Result3 : Symbol(Result3, Decl(keyRemappingKeyofResult3.ts, 185, 36)) +>AcceptA : Symbol(AcceptA, Decl(keyRemappingKeyofResult3.ts, 0, 0)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 180, 33)) +} + +type ValueIs1 = { [P in keyof T as T[P] extends 1 ? P : never]: any }; +>ValueIs1 : Symbol(ValueIs1, Decl(keyRemappingKeyofResult3.ts, 187, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 189, 14)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 189, 22)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 189, 14)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 189, 14)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 189, 22)) +>P : Symbol(P, Decl(keyRemappingKeyofResult3.ts, 189, 22)) + +type Base6 = { [key: string]: number; a: 1 }; +>Base6 : Symbol(Base6, Decl(keyRemappingKeyofResult3.ts, 189, 73)) +>key : Symbol(key, Decl(keyRemappingKeyofResult3.ts, 191, 16)) +>a : Symbol(a, Decl(keyRemappingKeyofResult3.ts, 191, 37)) + +function test22(k: keyof ValueIs1) { +>test22 : Symbol(test22, Decl(keyRemappingKeyofResult3.ts, 191, 45)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 193, 16)) +>Base6 : Symbol(Base6, Decl(keyRemappingKeyofResult3.ts, 189, 73)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 193, 33)) +>ValueIs1 : Symbol(ValueIs1, Decl(keyRemappingKeyofResult3.ts, 187, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult3.ts, 193, 16)) + + const s: string = k; // error +>s : Symbol(s, Decl(keyRemappingKeyofResult3.ts, 194, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 193, 33)) + + const s1: "a" = k; // error +>s1 : Symbol(s1, Decl(keyRemappingKeyofResult3.ts, 195, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 193, 33)) + + const s2: "a" | "b" = k; // error +>s2 : Symbol(s2, Decl(keyRemappingKeyofResult3.ts, 196, 7)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 193, 33)) + + type Result = AcceptString; // error +>Result : Symbol(Result, Decl(keyRemappingKeyofResult3.ts, 196, 26)) +>AcceptString : Symbol(AcceptString, Decl(keyRemappingKeyofResult3.ts, 1, 39)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 193, 33)) + + type Result2 = AcceptAB; // error +>Result2 : Symbol(Result2, Decl(keyRemappingKeyofResult3.ts, 197, 39)) +>AcceptAB : Symbol(AcceptAB, Decl(keyRemappingKeyofResult3.ts, 0, 32)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 193, 33)) + + type Result3 = AcceptA; // error +>Result3 : Symbol(Result3, Decl(keyRemappingKeyofResult3.ts, 198, 36)) +>AcceptA : Symbol(AcceptA, Decl(keyRemappingKeyofResult3.ts, 0, 0)) +>k : Symbol(k, Decl(keyRemappingKeyofResult3.ts, 193, 33)) +} + diff --git a/tests/baselines/reference/keyRemappingKeyofResult3.types b/tests/baselines/reference/keyRemappingKeyofResult3.types new file mode 100644 index 0000000000000..e6e6863742c9b --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult3.types @@ -0,0 +1,703 @@ +//// [tests/cases/compiler/keyRemappingKeyofResult3.ts] //// + +=== keyRemappingKeyofResult3.ts === +type AcceptA = T; +>AcceptA : T +> : ^ + +type AcceptAB = T; +>AcceptAB : T +> : ^ + +type AcceptString = T; +>AcceptString : T +> : ^ + +type Prefixed1 = { [K in keyof T as `pre_${K & string}`]: T[K] }; +>Prefixed1 : Prefixed1 +> : ^^^^^^^^^^^^ + +function test1(k: keyof Prefixed1) { +>test1 : (k: keyof Prefixed1) => void +> : ^ ^^ ^^ ^^^^^^^^^ +>k : keyof Prefixed1 +> : ^^^^^^^^^^^^^^^^^^ + + const a: `pre_${string}` = k; // ok +>a : `pre_${string}` +> : ^^^^^^^^^^^^^^^ +>k : keyof Prefixed1 +> : ^^^^^^^^^^^^^^^^^^ + + const b: `pre_a` | `pre_a` = k; // error +>b : "pre_a" +> : ^^^^^^^ +>k : keyof Prefixed1 +> : ^^^^^^^^^^^^^^^^^^ +} + +type RemapA = { [K in keyof T as `x_${K & string}`]: T[K] }; +>RemapA : RemapA +> : ^^^^^^^^^ + +type RemapB = { [K in keyof T as `x_${K & string}`]: number }; +>RemapB : RemapB +> : ^^^^^^^^^ + +function test2(ka: keyof RemapA, kb: keyof RemapB) { +>test2 : (ka: keyof RemapA, kb: keyof RemapB) => void +> : ^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>ka : keyof RemapA +> : ^^^^^^^^^^^^^^^ +>kb : keyof RemapB +> : ^^^^^^^^^^^^^^^ + + let a: keyof RemapA = kb; // ok +>a : keyof RemapA +> : ^^^^^^^^^^^^^^^ +>kb : keyof RemapB +> : ^^^^^^^^^^^^^^^ + + let b: keyof RemapB = ka; // ok +>b : keyof RemapB +> : ^^^^^^^^^^^^^^^ +>ka : keyof RemapA +> : ^^^^^^^^^^^^^^^ +} + +type Prefixed2 = { [P in K as `p_${P}`]: any }; +>Prefixed2 : Prefixed2 +> : ^^^^^^^^^^^^ + +function test3(k: keyof Prefixed2) { +>test3 : (k: keyof Prefixed2) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>k : keyof Prefixed2 +> : ^^^^^^^^^^^^^^^^^^ + + const a: `p_${string}` = k; // ok +>a : `p_${string}` +> : ^^^^^^^^^^^^^ +>k : keyof Prefixed2 +> : ^^^^^^^^^^^^^^^^^^ + + const b: `p_a` | `p_b` = k; // error +>b : "p_a" | "p_b" +> : ^^^^^^^^^^^^^ +>k : keyof Prefixed2 +> : ^^^^^^^^^^^^^^^^^^ +} + +type Prefixed3 = { [P in K as `p_${P}`]: any }; +>Prefixed3 : Prefixed3 +> : ^^^^^^^^^^^^ + +function test4(k: keyof Prefixed2) { +>test4 : (k: keyof Prefixed2) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>k : keyof Prefixed2 +> : ^^^^^^^^^^^^^^^^^^ + + const a: `p_${string}` = k; // ok +>a : `p_${string}` +> : ^^^^^^^^^^^^^ +>k : "p_a" | "p_b" +> : ^^^^^^^^^^^^^ + + const b: `p_a` | `p_b` = k; // ok +>b : "p_a" | "p_b" +> : ^^^^^^^^^^^^^ +>k : "p_a" | "p_b" +> : ^^^^^^^^^^^^^ + + const c: `p_a` = k; // error +>c : "p_a" +> : ^^^^^ +>k : "p_a" | "p_b" +> : ^^^^^^^^^^^^^ +} + +type OmitMapped = { +>OmitMapped : OmitMapped +> : ^^^^^^^^^^^^^^^^ + + [K in keyof T as Exclude]: T[K]; +}; + +function test5(k: keyof OmitMapped) { +>test5 : (k: keyof OmitMapped) => void +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>k : keyof OmitMapped +> : ^^^^^^^^^^^^^^^^^^^^^^ + + const x: Exclude = k; // ok +>x : Exclude +> : ^^^^^^^^^^^^^^^^^^^ +>k : keyof OmitMapped +> : ^^^^^^^^^^^^^^^^^^^^^^ +} + +type Uppercased = { [K in keyof T as Uppercase]: T[K] }; +>Uppercased : Uppercased +> : ^^^^^^^^^^^^^ + +function test6(k: keyof Uppercased) { +>test6 : (k: keyof Uppercased) => void +> : ^ ^^ ^^ ^^^^^^^^^ +>k : keyof Uppercased +> : ^^^^^^^^^^^^^^^^^^^ + + const a: Uppercase = k; // ok +>a : Uppercase +> : ^^^^^^^^^^^^^^^^^ +>k : keyof Uppercased +> : ^^^^^^^^^^^^^^^^^^^ +} + +type Base1 = { a: 1; b: 2 }; +>Base1 : Base1 +> : ^^^^^ +>a : 1 +> : ^ +>b : 2 +> : ^ + +type Constrained1 = { +>Constrained1 : Constrained1 +> : ^^^^^^^^^^^^^^^ + + [K in keyof T as `c_${K & string}`]: T[K]; +}; +type Constrained2 = { +>Constrained2 : Constrained2 +> : ^^^^^^^^^^^^^^^ + + [K in keyof T as `c_${K & string}`]: boolean; +}; + +function test7( +>test7 : (k1: keyof Constrained1, k2: keyof Constrained2) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ + + k1: keyof Constrained1, +>k1 : keyof Constrained1 +> : ^^^^^^^^^^^^^^^^^^^^^ + + k2: keyof Constrained2, +>k2 : keyof Constrained2 +> : ^^^^^^^^^^^^^^^^^^^^^ + +) { + let a: keyof Constrained1 = k2; // ok +>a : keyof Constrained1 +> : ^^^^^^^^^^^^^^^^^^^^^ +>k2 : keyof Constrained2 +> : ^^^^^^^^^^^^^^^^^^^^^ + + let b: keyof Constrained2 = k1; // ok +>b : keyof Constrained2 +> : ^^^^^^^^^^^^^^^^^^^^^ +>k1 : keyof Constrained1 +> : ^^^^^^^^^^^^^^^^^^^^^ +} + +function test8(k: keyof Constrained1) { +>test8 : (k: keyof Constrained1) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>k : keyof Constrained1 +> : ^^^^^^^^^^^^^^^^^^^^^ + + const a: "c_a" | "c_b" = k; // error +>a : "c_a" | "c_b" +> : ^^^^^^^^^^^^^ +>k : keyof Constrained1 +> : ^^^^^^^^^^^^^^^^^^^^^ + + const b: `c_${string}` = k; // ok +>b : `c_${string}` +> : ^^^^^^^^^^^^^ +>k : keyof Constrained1 +> : ^^^^^^^^^^^^^^^^^^^^^ +} + +type StringPropsOnly = { +>StringPropsOnly : StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^ + + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function test9(k: Extract, string>) { +>test9 : (k: Extract, string>) => void +> : ^ ^^ ^^ ^^^^^^^^^ +>k : Extract, string> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const s: string = k; // ok +>s : string +> : ^^^^^^ +>k : Extract, string> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result = AcceptString; // ok +>Result : Extract, string> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : Extract, string> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +type AllKeysMapped = { [P in keyof T as P]: any }; +>AllKeysMapped : AllKeysMapped +> : ^^^^^^^^^^^^^^^^ + +function test10(k: Extract, string>) { +>test10 : (k: Extract, string>) => void +> : ^ ^^ ^^ ^^^^^^^^^ +>k : Extract, string> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const s: string = k; // ok +>s : string +> : ^^^^^^ +>k : Extract, string> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result = AcceptString; // ok +>Result : Extract, string> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : Extract, string> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +function test11(k: keyof StringPropsOnly) { +>test11 : (k: keyof StringPropsOnly) => void +> : ^ ^^ ^^ ^^^^^^^^^ +>k : keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + const s: string = k; // error +>s : string +> : ^^^^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result = AcceptString; // error +>Result : keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +} + +function test12(k: string & keyof StringPropsOnly) { +>test12 : (k: string & keyof StringPropsOnly) => void +> : ^ ^^ ^^ ^^^^^^^^^ +>k : string & keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const s: string = k; // ok +>s : string +> : ^^^^^^ +>k : string +> : ^^^^^^ + + type Result = AcceptString; // ok +>Result : string & keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : string & keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +type FilterByLiteralValue = { +>FilterByLiteralValue : FilterByLiteralValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [P in keyof T as T[P] extends V ? P : never]: any; +}; + +function test13(k: keyof FilterByLiteralValue) { +>test13 : (k: keyof FilterByLiteralValue) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>k : keyof FilterByLiteralValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const s: string = k; // error +>s : string +> : ^^^^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result = AcceptString; // error +>Result : keyof FilterByLiteralValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof FilterByLiteralValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +type Base2 = { x: string; y: number }; +>Base2 : Base2 +> : ^^^^^ +>x : string +> : ^^^^^^ +>y : number +> : ^^^^^^ + +type FilterByStringValue = { +>FilterByStringValue : FilterByStringValue +> : ^^^^^^^^^^^^^^^^^^^^^^ + + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function test14(k: keyof FilterByStringValue) { +>test14 : (k: keyof FilterByStringValue) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>k : keyof FilterByStringValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const s: string = k; // error +>s : string +> : ^^^^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + const s2: "x" = k; // error +>s2 : "x" +> : ^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result1 = AcceptString; // error +>Result1 : keyof FilterByStringValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof FilterByStringValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result2 = AcceptAB; // error +>Result2 : keyof FilterByStringValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof FilterByStringValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result3 = AcceptA; // error +>Result3 : keyof FilterByStringValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof FilterByStringValue +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +type RemapC = { [P in keyof T as T[P] extends string ? P : never]: T[P] }; +>RemapC : RemapC +> : ^^^^^^^^^ + +type RemapD = { [P in keyof T as T[P] extends string ? P : never]: number }; +>RemapD : RemapD +> : ^^^^^^^^^ + +function test15(ka: keyof RemapC, kb: keyof RemapD) { +>test15 : (ka: keyof RemapC, kb: keyof RemapD) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>ka : keyof RemapC +> : ^^^^^^^^^^^^^^^ +>kb : keyof RemapD +> : ^^^^^^^^^^^^^^^ + + let a: keyof RemapC = kb; // ok +>a : keyof RemapC +> : ^^^^^^^^^^^^^^^ +>kb : keyof RemapD +> : ^^^^^^^^^^^^^^^ + + let b: keyof RemapD = ka; // ok +>b : keyof RemapD +> : ^^^^^^^^^^^^^^^ +>ka : keyof RemapC +> : ^^^^^^^^^^^^^^^ +} + +type Base3 = { a: string; b: string; c: string }; +>Base3 : Base3 +> : ^^^^^ +>a : string +> : ^^^^^^ +>b : string +> : ^^^^^^ +>c : string +> : ^^^^^^ + +type AlwaysNever = { [P in keyof T as 1 extends string ? P : never]: any }; +>AlwaysNever : AlwaysNever +> : ^^^^^^^^^^^^^^ + +function test16(k: keyof AlwaysNever) { +>test16 : (k: keyof AlwaysNever) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>k : keyof AlwaysNever +> : ^^^^^^^^^^^^^^^^^^^^ + + const s: string = k; // ok +>s : string +> : ^^^^^^ +>k : keyof AlwaysNever +> : ^^^^^^^^^^^^^^^^^^^^ + + type Result = AcceptString; // ok +>Result : keyof AlwaysNever +> : ^^^^^^^^^^^^^^^^^^^^ +>k : keyof AlwaysNever +> : ^^^^^^^^^^^^^^^^^^^^ +} + +type Base4 = { a: string; b: number }; +>Base4 : Base4 +> : ^^^^^ +>a : string +> : ^^^^^^ +>b : number +> : ^^^^^^ + +type PickByType = { [P in keyof T as T[P] extends V ? P : never]: T[P] }; +>PickByType : PickByType +> : ^^^^^^^^^^^^^^^^ + +function test17(k: keyof PickByType) { +>test17 : (k: keyof PickByType) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>k : keyof PickByType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const s: string = k; // error +>s : string +> : ^^^^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + const s2: typeof k = "a"; // error (checks against a deferred conditional type) +>s2 : keyof PickByType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof PickByType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"a" : "a" +> : ^^^ + + const s3: "a" = k; // error +>s3 : "a" +> : ^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result = AcceptString; // error +>Result : keyof PickByType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof PickByType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result2 = AcceptAB; // error +>Result2 : keyof PickByType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof PickByType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result3 = AcceptA; // error +>Result3 : keyof PickByType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof PickByType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +function test18(o: { +>test18 : (o: { [P in keyof T as T[P] extends string ? P : never]: any; }) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>a : string +> : ^^^^^^ +>b : number +> : ^^^^^^ +>o : { [P in keyof T as T[P] extends string ? P : never]: any; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + [P in keyof T as T[P] extends string ? P : never]: any; +}) { + type Result = AcceptString; // error +>Result : keyof { [P in keyof T as T[P] extends string ? P : never]: any; } +> : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>o : { [P in keyof T as T[P] extends string ? P : never]: any; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +type Inner = { [P in keyof T as P extends string ? P : never]: T[P] }; +>Inner : Inner +> : ^^^^^^^^ + +type Outer = { +>Outer : Outer +> : ^^^^^^^^ + + [P in keyof Inner as P extends `a${string}` ? P : never]: any; +}; + +function test19( +>test19 : (k: keyof Outer) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>apple : 1 +> : ^ +>apricot : 2 +> : ^ +>banana : 3 +> : ^ + + k: keyof Outer, +>k : keyof Outer +> : ^^^^^^^^^^^^^^ + +) { + const s: string = k; // ok +>s : string +> : ^^^^^^ +>k : keyof Outer +> : ^^^^^^^^^^^^^^ + + type Result = AcceptString; // ok +>Result : keyof Outer +> : ^^^^^^^^^^^^^^ +>k : keyof Outer +> : ^^^^^^^^^^^^^^ +} + +type Prefixed4 = { +>Prefixed4 : Prefixed4 +> : ^^^^^^^^^^^^ + + [P in keyof T as P extends string ? `mapped_${P}` : never]: any; +}; + +function test20( +>test20 : (k: keyof Prefixed4) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>key : string +> : ^^^^^^ +>specific : 1 +> : ^ + + k: keyof Prefixed4, +>k : keyof Prefixed4 +> : ^^^^^^^^^^^^^^^^^^ + +) { + const s: string = k; // ok +>s : string +> : ^^^^^^ +>k : keyof Prefixed4 +> : ^^^^^^^^^^^^^^^^^^ + + type Result = AcceptString; // ok +>Result : keyof Prefixed4 +> : ^^^^^^^^^^^^^^^^^^ +>k : keyof Prefixed4 +> : ^^^^^^^^^^^^^^^^^^ +} + +type Base5 = { a: string; b: number | string }; +>Base5 : Base5 +> : ^^^^^ +>a : string +> : ^^^^^^ +>b : string | number +> : ^^^^^^^^^^^^^^^ + +function test21(k: keyof StringPropsOnly) { +>test21 : (k: keyof StringPropsOnly) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>k : keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + const s: string = k; // error +>s : string +> : ^^^^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + const s1: "a" = k; // error +>s1 : "a" +> : ^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + const s2: "a" | "b" = k; // error +>s2 : "a" | "b" +> : ^^^^^^^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result = AcceptString; // error +>Result : keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result2 = AcceptAB; // error +>Result2 : keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result3 = AcceptA; // error +>Result3 : keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>k : keyof StringPropsOnly +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +} + +type ValueIs1 = { [P in keyof T as T[P] extends 1 ? P : never]: any }; +>ValueIs1 : ValueIs1 +> : ^^^^^^^^^^^ + +type Base6 = { [key: string]: number; a: 1 }; +>Base6 : Base6 +> : ^^^^^ +>key : string +> : ^^^^^^ +>a : 1 +> : ^ + +function test22(k: keyof ValueIs1) { +>test22 : (k: keyof ValueIs1) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^ +>k : keyof ValueIs1 +> : ^^^^^^^^^^^^^^^^^ + + const s: string = k; // error +>s : string +> : ^^^^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + const s1: "a" = k; // error +>s1 : "a" +> : ^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + const s2: "a" | "b" = k; // error +>s2 : "a" | "b" +> : ^^^^^^^^^ +>k : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + type Result = AcceptString; // error +>Result : keyof ValueIs1 +> : ^^^^^^^^^^^^^^^^^ +>k : keyof ValueIs1 +> : ^^^^^^^^^^^^^^^^^ + + type Result2 = AcceptAB; // error +>Result2 : keyof ValueIs1 +> : ^^^^^^^^^^^^^^^^^ +>k : keyof ValueIs1 +> : ^^^^^^^^^^^^^^^^^ + + type Result3 = AcceptA; // error +>Result3 : keyof ValueIs1 +> : ^^^^^^^^^^^^^^^^^ +>k : keyof ValueIs1 +> : ^^^^^^^^^^^^^^^^^ +} + diff --git a/tests/cases/compiler/keyRemappingKeyofResult.ts b/tests/cases/compiler/keyRemappingKeyofResult.ts index ba0b0939ae3cb..f7957cb7ffec8 100644 --- a/tests/cases/compiler/keyRemappingKeyofResult.ts +++ b/tests/cases/compiler/keyRemappingKeyofResult.ts @@ -1,3 +1,4 @@ +// @strict: true, false // @target: es6 const sym = Symbol("") type Orig = { [k: string]: any, str: any, [sym]: any } @@ -21,21 +22,21 @@ x = "str"; // equivalently, with an unresolved generic (no `exclude` shenanigans, since conditions won't execute): function f() { type Orig = { [k: string]: any, str: any, [sym]: any } & T; - + type Okay = keyof Orig; let a: Okay; a = "str"; a = sym; a = "whatever"; // type Okay = string | number | typeof sym - + type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } /* type Remapped = { str: any; [sym]: any; } */ // no string index signature, right? - + type Oops = keyof Remapped; let x: Oops; x = sym; @@ -45,7 +46,7 @@ function f() { // and another generic case with a _distributive_ mapping, to trigger a different branch in `getIndexType` function g() { type Orig = { [k: string]: any, str: any, [sym]: any } & T; - + type Okay = keyof Orig; let a: Okay; a = "str"; @@ -55,14 +56,14 @@ function g() { type NonIndex = {} extends Record ? never : T; type DistributiveNonIndex = T extends unknown ? NonIndex : never; - + type Remapped = { [K in keyof Orig as DistributiveNonIndex]: any } /* type Remapped = { str: any; [sym]: any; } */ // no string index signature, right? - + type Oops = keyof Remapped; let x: Oops; x = sym; @@ -70,4 +71,27 @@ function g() { x = "whatever"; // error } -export {}; \ No newline at end of file +// https://github.com/microsoft/TypeScript/issues/57827 + +type StringKeys = Extract< + keyof { + [P in keyof T as T[P] extends string ? P : never]: any; + }, + string +>; + +function test_57827(z: StringKeys) { + const f: string = z; + z = "foo"; // error +} + +type StringKeys2 = keyof { + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function h(z: StringKeys2) { + z = "foo"; // error + const f: string = z; // ok +} + +export {}; diff --git a/tests/cases/compiler/keyRemappingKeyofResult3.ts b/tests/cases/compiler/keyRemappingKeyofResult3.ts new file mode 100644 index 0000000000000..569b91e15064d --- /dev/null +++ b/tests/cases/compiler/keyRemappingKeyofResult3.ts @@ -0,0 +1,204 @@ +// @strict: true +// @noEmit: true + +type AcceptA = T; +type AcceptAB = T; +type AcceptString = T; + +type Prefixed1 = { [K in keyof T as `pre_${K & string}`]: T[K] }; + +function test1(k: keyof Prefixed1) { + const a: `pre_${string}` = k; // ok + const b: `pre_a` | `pre_a` = k; // error +} + +type RemapA = { [K in keyof T as `x_${K & string}`]: T[K] }; +type RemapB = { [K in keyof T as `x_${K & string}`]: number }; + +function test2(ka: keyof RemapA, kb: keyof RemapB) { + let a: keyof RemapA = kb; // ok + let b: keyof RemapB = ka; // ok +} + +type Prefixed2 = { [P in K as `p_${P}`]: any }; + +function test3(k: keyof Prefixed2) { + const a: `p_${string}` = k; // ok + const b: `p_a` | `p_b` = k; // error +} + +type Prefixed3 = { [P in K as `p_${P}`]: any }; + +function test4(k: keyof Prefixed2) { + const a: `p_${string}` = k; // ok + const b: `p_a` | `p_b` = k; // ok + const c: `p_a` = k; // error +} + +type OmitMapped = { + [K in keyof T as Exclude]: T[K]; +}; + +function test5(k: keyof OmitMapped) { + const x: Exclude = k; // ok +} + +type Uppercased = { [K in keyof T as Uppercase]: T[K] }; + +function test6(k: keyof Uppercased) { + const a: Uppercase = k; // ok +} + +type Base1 = { a: 1; b: 2 }; +type Constrained1 = { + [K in keyof T as `c_${K & string}`]: T[K]; +}; +type Constrained2 = { + [K in keyof T as `c_${K & string}`]: boolean; +}; + +function test7( + k1: keyof Constrained1, + k2: keyof Constrained2, +) { + let a: keyof Constrained1 = k2; // ok + let b: keyof Constrained2 = k1; // ok +} + +function test8(k: keyof Constrained1) { + const a: "c_a" | "c_b" = k; // error + const b: `c_${string}` = k; // ok +} + +type StringPropsOnly = { + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function test9(k: Extract, string>) { + const s: string = k; // ok + type Result = AcceptString; // ok +} + +type AllKeysMapped = { [P in keyof T as P]: any }; + +function test10(k: Extract, string>) { + const s: string = k; // ok + type Result = AcceptString; // ok +} + +function test11(k: keyof StringPropsOnly) { + const s: string = k; // error + type Result = AcceptString; // error +} + +function test12(k: string & keyof StringPropsOnly) { + const s: string = k; // ok + type Result = AcceptString; // ok +} + +type FilterByLiteralValue = { + [P in keyof T as T[P] extends V ? P : never]: any; +}; + +function test13(k: keyof FilterByLiteralValue) { + const s: string = k; // error + type Result = AcceptString; // error +} + +type Base2 = { x: string; y: number }; + +type FilterByStringValue = { + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function test14(k: keyof FilterByStringValue) { + const s: string = k; // error + const s2: "x" = k; // error + type Result1 = AcceptString; // error + type Result2 = AcceptAB; // error + type Result3 = AcceptA; // error +} + +type RemapC = { [P in keyof T as T[P] extends string ? P : never]: T[P] }; +type RemapD = { [P in keyof T as T[P] extends string ? P : never]: number }; + +function test15(ka: keyof RemapC, kb: keyof RemapD) { + let a: keyof RemapC = kb; // ok + let b: keyof RemapD = ka; // ok +} + +type Base3 = { a: string; b: string; c: string }; + +type AlwaysNever = { [P in keyof T as 1 extends string ? P : never]: any }; + +function test16(k: keyof AlwaysNever) { + const s: string = k; // ok + type Result = AcceptString; // ok +} + +type Base4 = { a: string; b: number }; + +type PickByType = { [P in keyof T as T[P] extends V ? P : never]: T[P] }; + +function test17(k: keyof PickByType) { + const s: string = k; // error + const s2: typeof k = "a"; // error (checks against a deferred conditional type) + const s3: "a" = k; // error + + type Result = AcceptString; // error + type Result2 = AcceptAB; // error + type Result3 = AcceptA; // error +} + +function test18(o: { + [P in keyof T as T[P] extends string ? P : never]: any; +}) { + type Result = AcceptString; // error +} + +type Inner = { [P in keyof T as P extends string ? P : never]: T[P] }; +type Outer = { + [P in keyof Inner as P extends `a${string}` ? P : never]: any; +}; + +function test19( + k: keyof Outer, +) { + const s: string = k; // ok + type Result = AcceptString; // ok +} + +type Prefixed4 = { + [P in keyof T as P extends string ? `mapped_${P}` : never]: any; +}; + +function test20( + k: keyof Prefixed4, +) { + const s: string = k; // ok + type Result = AcceptString; // ok +} + +type Base5 = { a: string; b: number | string }; + +function test21(k: keyof StringPropsOnly) { + const s: string = k; // error + const s1: "a" = k; // error + const s2: "a" | "b" = k; // error + type Result = AcceptString; // error + type Result2 = AcceptAB; // error + type Result3 = AcceptA; // error +} + +type ValueIs1 = { [P in keyof T as T[P] extends 1 ? P : never]: any }; + +type Base6 = { [key: string]: number; a: 1 }; + +function test22(k: keyof ValueIs1) { + const s: string = k; // error + const s1: "a" = k; // error + const s2: "a" | "b" = k; // error + type Result = AcceptString; // error + type Result2 = AcceptAB; // error + type Result3 = AcceptA; // error +}