From 1a27fd94e27e1235e70ae8b7be763c599a8246ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 19 Mar 2024 00:19:24 +0100 Subject: [PATCH 1/6] Fixed an issue with apparent mapped type keys --- src/compiler/checker.ts | 2 +- ... keyRemappingKeyofResult(strict=false).js} | 16 ++ ...emappingKeyofResult(strict=false).symbols} | 31 +++ ...yRemappingKeyofResult(strict=false).types} | 20 ++ .../keyRemappingKeyofResult(strict=true).js | 117 +++++++++ ...yRemappingKeyofResult(strict=true).symbols | 226 ++++++++++++++++++ ...keyRemappingKeyofResult(strict=true).types | 195 +++++++++++++++ .../cases/compiler/keyRemappingKeyofResult.ts | 14 ++ 8 files changed, 620 insertions(+), 1 deletion(-) rename tests/baselines/reference/{keyRemappingKeyofResult.js => keyRemappingKeyofResult(strict=false).js} (88%) rename tests/baselines/reference/{keyRemappingKeyofResult.symbols => keyRemappingKeyofResult(strict=false).symbols} (84%) rename tests/baselines/reference/{keyRemappingKeyofResult.types => keyRemappingKeyofResult(strict=false).types} (88%) create mode 100644 tests/baselines/reference/keyRemappingKeyofResult(strict=true).js create mode 100644 tests/baselines/reference/keyRemappingKeyofResult(strict=true).symbols create mode 100644 tests/baselines/reference/keyRemappingKeyofResult(strict=true).types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8ba4d7d896f8b..ac9d81329b73e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22486,7 +22486,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /*stringsOnly*/ false, t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(targetType.mapper, getTypeParameterFromMappedType(targetType), t))), ); - return getUnionType(mappedKeys); + return mappedKeys.length ? getUnionType(mappedKeys) : stringNumberSymbolType; } function structuredTypeRelatedToWorker(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, saveErrorInfo: ReturnType): Ternary { diff --git a/tests/baselines/reference/keyRemappingKeyofResult.js b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).js similarity index 88% rename from tests/baselines/reference/keyRemappingKeyofResult.js rename to tests/baselines/reference/keyRemappingKeyofResult(strict=false).js index 3b51e02dc735e..4107cfd488ca1 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult.js +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).js @@ -71,6 +71,19 @@ function g() { x = "str"; } +// 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; +} + export {}; //// [keyRemappingKeyofResult.js] @@ -98,4 +111,7 @@ function g() { x = sym; x = "str"; } +function test_57827(z) { + const f = z; +} export {}; diff --git a/tests/baselines/reference/keyRemappingKeyofResult.symbols b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols similarity index 84% rename from tests/baselines/reference/keyRemappingKeyofResult.symbols rename to tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols index 722c000f268fa..8e9cde0acfb91 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult.symbols +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols @@ -192,4 +192,35 @@ 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, 68, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 72, 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, 74, 5)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 72, 16)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 72, 16)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 74, 5)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 74, 5)) + + }, + string +>; + +function test_57827(z: StringKeys) { +>test_57827 : Symbol(test_57827, Decl(keyRemappingKeyofResult.ts, 77, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 79, 20)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 79, 23)) +>StringKeys : Symbol(StringKeys, Decl(keyRemappingKeyofResult.ts, 68, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 79, 20)) + + const f: string = z; +>f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 80, 7)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 79, 23)) +} + export {}; diff --git a/tests/baselines/reference/keyRemappingKeyofResult.types b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types similarity index 88% rename from tests/baselines/reference/keyRemappingKeyofResult.types rename to tests/baselines/reference/keyRemappingKeyofResult(strict=false).types index 01569ae0ddeed..07b898a527d1d 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult.types +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types @@ -172,4 +172,24 @@ function g() { >"str" : "str" } +// 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 +} + export {}; diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js new file mode 100644 index 0000000000000..4107cfd488ca1 --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js @@ -0,0 +1,117 @@ +//// [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"; +} + +// 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; +} + +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"; +} +function test_57827(z) { + const f = z; +} +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..8e9cde0acfb91 --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).symbols @@ -0,0 +1,226 @@ +//// [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)) +} + +// https://github.com/microsoft/TypeScript/issues/57827 + +type StringKeys = Extract< +>StringKeys : Symbol(StringKeys, Decl(keyRemappingKeyofResult.ts, 68, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 72, 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, 74, 5)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 72, 16)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 72, 16)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 74, 5)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 74, 5)) + + }, + string +>; + +function test_57827(z: StringKeys) { +>test_57827 : Symbol(test_57827, Decl(keyRemappingKeyofResult.ts, 77, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 79, 20)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 79, 23)) +>StringKeys : Symbol(StringKeys, Decl(keyRemappingKeyofResult.ts, 68, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 79, 20)) + + const f: string = z; +>f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 80, 7)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 79, 23)) +} + +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..07b898a527d1d --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types @@ -0,0 +1,195 @@ +//// [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 : { [k: string]: any; str: any; [sym]: any; } +>k : string +>str : any +>[sym] : any +>sym : unique symbol + +type Okay = Exclude +>Okay : string | number | unique symbol + +// type Okay = string | number | typeof sym + +type Remapped = { [K in keyof Orig as {} extends Record ? never : K]: any } +>Remapped : { str: any; [sym]: any; } + +/* type Remapped = { + str: any; + [sym]: any; +} */ +// no string index signature, right? + +type Oops = Exclude +>Oops : unique symbol | "str" + +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" +} + +// 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 +} + +export {}; diff --git a/tests/cases/compiler/keyRemappingKeyofResult.ts b/tests/cases/compiler/keyRemappingKeyofResult.ts index fcf3f835ac691..c376f0662a21c 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 } @@ -69,4 +70,17 @@ function g() { x = "str"; } +// 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; +} + export {}; \ No newline at end of file From 04976bff8e0e58fa00c5ceff8d630586168be098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 25 Nov 2024 00:13:09 +0100 Subject: [PATCH 2/6] improve the fix --- src/compiler/checker.ts | 21 +++- ...appingKeyofResult(strict=false).errors.txt | 105 ++++++++++++++++++ .../keyRemappingKeyofResult(strict=false).js | 28 +++-- ...RemappingKeyofResult(strict=false).symbols | 40 ++++++- ...eyRemappingKeyofResult(strict=false).types | 49 +++++++- ...mappingKeyofResult(strict=true).errors.txt | 105 ++++++++++++++++++ .../keyRemappingKeyofResult(strict=true).js | 28 +++-- ...yRemappingKeyofResult(strict=true).symbols | 40 ++++++- ...keyRemappingKeyofResult(strict=true).types | 49 +++++++- .../cases/compiler/keyRemappingKeyofResult.ts | 23 ++-- 10 files changed, 438 insertions(+), 50 deletions(-) create mode 100644 tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt create mode 100644 tests/baselines/reference/keyRemappingKeyofResult(strict=true).errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fa0483015faca..a33516c702fc3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22895,16 +22895,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function getApparentMappedTypeKeys(nameType: Type, targetType: MappedType) { - const modifiersType = getApparentType(getModifiersTypeFromMappedType(targetType)); + function getApparentMappedTypeKeys(nameType: Type, mappedType: MappedType) { + const modifiersType = getApparentType(getModifiersTypeFromMappedType(mappedType)); const mappedKeys: Type[] = []; forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType( modifiersType, TypeFlags.StringOrNumberLiteralOrUnique, /*stringsOnly*/ false, - t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(targetType.mapper, getTypeParameterFromMappedType(targetType), t))), + t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(mappedType.mapper, getTypeParameterFromMappedType(mappedType), t))), ); - return mappedKeys.length ? getUnionType(mappedKeys) : stringNumberSymbolType; + return getUnionType(mappedKeys); } function structuredTypeRelatedToWorker(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, saveErrorInfo: ReturnType): Ternary { @@ -23277,7 +23277,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // 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)); + let sourceMappedKeys: Type; + if (nameType && isMappedTypeWithKeyofConstraintDeclaration(mappedType)) { + sourceMappedKeys = getApparentMappedTypeKeys(nameType, mappedType); + if (sourceMappedKeys.flags & TypeFlags.Never) { + // modifiers type of mapped type is often `unknown`, `keyof unknown` is `never` and that's assignable to everything + // letting this through is too permissive so we use the apparent type of an index type here instead + sourceMappedKeys = stringNumberSymbolType; + } + } + else { + sourceMappedKeys = nameType || getConstraintTypeFromMappedType(mappedType); + } if (result = isRelatedTo(sourceMappedKeys, target, RecursionFlags.Source, reportErrors)) { return result; } diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt new file mode 100644 index 0000000000000..5f69889fa7e76 --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt @@ -0,0 +1,105 @@ +keyRemappingKeyofResult.ts(82,3): error TS2322: Type 'string' is not assignable to type 'Extract'. +keyRemappingKeyofResult.ts(90,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 (2 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"; + } + + // 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'. + } + + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).js b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).js index 4107cfd488ca1..7169b9e7ef77d 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).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; @@ -82,9 +82,19 @@ type StringKeys = Extract< function test_57827(z: StringKeys) { const f: string = z; + z = "foo"; // error } -export {}; +type StringKeys2 = keyof { + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function h(z: StringKeys2) { + z = "foo"; // error +} + +export {}; + //// [keyRemappingKeyofResult.js] const sym = Symbol(""); @@ -113,5 +123,9 @@ function g() { } function test_57827(z) { const f = z; + z = "foo"; // error +} +function h(z) { + z = "foo"; // error } export {}; diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols index 8e9cde0acfb91..8e49e52eab8a4 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).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)) @@ -220,7 +220,35 @@ function test_57827(z: StringKeys) { const f: string = z; >f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 80, 7)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 79, 23)) + + z = "foo"; // error >z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 79, 23)) } +type StringKeys2 = keyof { +>StringKeys2 : Symbol(StringKeys2, Decl(keyRemappingKeyofResult.ts, 82, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 84, 17)) + + [P in keyof T as T[P] extends string ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 85, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 84, 17)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 84, 17)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 85, 3)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 85, 3)) + +}; + +function h(z: StringKeys2) { +>h : Symbol(h, Decl(keyRemappingKeyofResult.ts, 86, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 88, 11)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 88, 14)) +>StringKeys2 : Symbol(StringKeys2, Decl(keyRemappingKeyofResult.ts, 82, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 88, 11)) + + z = "foo"; // error +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 88, 14)) +} + export {}; + diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types index 8d3983d62f1eb..9dd85908b9966 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types @@ -17,7 +17,9 @@ type Orig = { [k: string]: any, str: any, [sym]: any } >k : string > : ^^^^^^ >str : any +> : ^^^ >[sym] : any +> : ^^^ >sym : unique symbol > : ^^^^^^^^^^^^^ @@ -74,10 +76,12 @@ function f() { >k : string > : ^^^^^^ >str : any +> : ^^^ >[sym] : any +> : ^^^ >sym : unique symbol > : ^^^^^^^^^^^^^ - + type Okay = keyof Orig; >Okay : string | number | unique symbol | keyof T > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,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; } > : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,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; } > : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,10 +162,12 @@ function g() { >k : string > : ^^^^^^ >str : any +> : ^^^ >[sym] : any +> : ^^^ >sym : unique symbol > : ^^^^^^^^^^^^^ - + type Okay = keyof Orig; >Okay : string | number | unique symbol | keyof T > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -203,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; } > : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -213,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; } > : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -262,6 +268,37 @@ function test_57827(z: StringKeys) { > : ^^^^^^ >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" +> : ^^^^^ } 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..5f69889fa7e76 --- /dev/null +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).errors.txt @@ -0,0 +1,105 @@ +keyRemappingKeyofResult.ts(82,3): error TS2322: Type 'string' is not assignable to type 'Extract'. +keyRemappingKeyofResult.ts(90,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 (2 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"; + } + + // 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'. + } + + 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 index 4107cfd488ca1..7169b9e7ef77d 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).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; @@ -82,9 +82,19 @@ type StringKeys = Extract< function test_57827(z: StringKeys) { const f: string = z; + z = "foo"; // error } -export {}; +type StringKeys2 = keyof { + [P in keyof T as T[P] extends string ? P : never]: any; +}; + +function h(z: StringKeys2) { + z = "foo"; // error +} + +export {}; + //// [keyRemappingKeyofResult.js] const sym = Symbol(""); @@ -113,5 +123,9 @@ function g() { } function test_57827(z) { const f = z; + z = "foo"; // error +} +function h(z) { + z = "foo"; // error } export {}; diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).symbols b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).symbols index 8e9cde0acfb91..8e49e52eab8a4 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).symbols +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).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)) @@ -220,7 +220,35 @@ function test_57827(z: StringKeys) { const f: string = z; >f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 80, 7)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 79, 23)) + + z = "foo"; // error >z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 79, 23)) } +type StringKeys2 = keyof { +>StringKeys2 : Symbol(StringKeys2, Decl(keyRemappingKeyofResult.ts, 82, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 84, 17)) + + [P in keyof T as T[P] extends string ? P : never]: any; +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 85, 3)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 84, 17)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 84, 17)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 85, 3)) +>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 85, 3)) + +}; + +function h(z: StringKeys2) { +>h : Symbol(h, Decl(keyRemappingKeyofResult.ts, 86, 2)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 88, 11)) +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 88, 14)) +>StringKeys2 : Symbol(StringKeys2, Decl(keyRemappingKeyofResult.ts, 82, 1)) +>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 88, 11)) + + z = "foo"; // error +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 88, 14)) +} + export {}; + diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types index 8d3983d62f1eb..9dd85908b9966 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types @@ -17,7 +17,9 @@ type Orig = { [k: string]: any, str: any, [sym]: any } >k : string > : ^^^^^^ >str : any +> : ^^^ >[sym] : any +> : ^^^ >sym : unique symbol > : ^^^^^^^^^^^^^ @@ -74,10 +76,12 @@ function f() { >k : string > : ^^^^^^ >str : any +> : ^^^ >[sym] : any +> : ^^^ >sym : unique symbol > : ^^^^^^^^^^^^^ - + type Okay = keyof Orig; >Okay : string | number | unique symbol | keyof T > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,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; } > : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,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; } > : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,10 +162,12 @@ function g() { >k : string > : ^^^^^^ >str : any +> : ^^^ >[sym] : any +> : ^^^ >sym : unique symbol > : ^^^^^^^^^^^^^ - + type Okay = keyof Orig; >Okay : string | number | unique symbol | keyof T > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -203,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; } > : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -213,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; } > : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -262,6 +268,37 @@ function test_57827(z: StringKeys) { > : ^^^^^^ >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" +> : ^^^^^ } export {}; + diff --git a/tests/cases/compiler/keyRemappingKeyofResult.ts b/tests/cases/compiler/keyRemappingKeyofResult.ts index c376f0662a21c..89f14004660ef 100644 --- a/tests/cases/compiler/keyRemappingKeyofResult.ts +++ b/tests/cases/compiler/keyRemappingKeyofResult.ts @@ -22,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; @@ -46,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"; @@ -56,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; @@ -81,6 +81,15 @@ type StringKeys = Extract< 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 } -export {}; \ No newline at end of file +export {}; From cad532adfb753a6737111526120824443030e30b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 30 Nov 2024 16:21:32 +0100 Subject: [PATCH 3/6] add extra test case --- .../keyRemappingKeyofResult(strict=false).errors.txt | 1 + .../reference/keyRemappingKeyofResult(strict=false).js | 2 ++ .../reference/keyRemappingKeyofResult(strict=false).symbols | 4 ++++ .../reference/keyRemappingKeyofResult(strict=false).types | 6 ++++++ .../keyRemappingKeyofResult(strict=true).errors.txt | 1 + .../reference/keyRemappingKeyofResult(strict=true).js | 2 ++ .../reference/keyRemappingKeyofResult(strict=true).symbols | 4 ++++ .../reference/keyRemappingKeyofResult(strict=true).types | 6 ++++++ tests/cases/compiler/keyRemappingKeyofResult.ts | 1 + 9 files changed, 27 insertions(+) diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt index 5f69889fa7e76..a072e3be92b17 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).errors.txt @@ -99,6 +99,7 @@ keyRemappingKeyofResult.ts(90,3): error TS2322: Type 'string' is not assignable ~ !!! 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 {}; diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).js b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).js index 7169b9e7ef77d..c46149d6c8d44 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).js +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).js @@ -91,6 +91,7 @@ type StringKeys2 = keyof { function h(z: StringKeys2) { z = "foo"; // error + const f: string = z; // ok } export {}; @@ -127,5 +128,6 @@ function test_57827(z) { } function h(z) { z = "foo"; // error + const f = z; // ok } export {}; diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols index 8e49e52eab8a4..cea827e0f2f5c 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols @@ -247,6 +247,10 @@ function h(z: StringKeys2) { >T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 88, 11)) z = "foo"; // error +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 88, 14)) + + const f: string = z; // ok +>f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 90, 7)) >z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 88, 14)) } diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types index 9dd85908b9966..83fe33b0104a2 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=false).types @@ -298,6 +298,12 @@ function h(z: StringKeys2) { > : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >"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 index 5f69889fa7e76..a072e3be92b17 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).errors.txt +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).errors.txt @@ -99,6 +99,7 @@ keyRemappingKeyofResult.ts(90,3): error TS2322: Type 'string' is not assignable ~ !!! 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 {}; diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js index 7169b9e7ef77d..c46149d6c8d44 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).js @@ -91,6 +91,7 @@ type StringKeys2 = keyof { function h(z: StringKeys2) { z = "foo"; // error + const f: string = z; // ok } export {}; @@ -127,5 +128,6 @@ function test_57827(z) { } 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 index 8e49e52eab8a4..cea827e0f2f5c 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).symbols +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).symbols @@ -247,6 +247,10 @@ function h(z: StringKeys2) { >T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 88, 11)) z = "foo"; // error +>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 88, 14)) + + const f: string = z; // ok +>f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 90, 7)) >z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 88, 14)) } diff --git a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types index 9dd85908b9966..83fe33b0104a2 100644 --- a/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types +++ b/tests/baselines/reference/keyRemappingKeyofResult(strict=true).types @@ -298,6 +298,12 @@ function h(z: StringKeys2) { > : ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >"foo" : "foo" > : ^^^^^ + + const f: string = z; // ok +>f : string +> : ^^^^^^ +>z : string +> : ^^^^^^ } export {}; diff --git a/tests/cases/compiler/keyRemappingKeyofResult.ts b/tests/cases/compiler/keyRemappingKeyofResult.ts index 89f14004660ef..2cec329384b29 100644 --- a/tests/cases/compiler/keyRemappingKeyofResult.ts +++ b/tests/cases/compiler/keyRemappingKeyofResult.ts @@ -90,6 +90,7 @@ type StringKeys2 = keyof { function h(z: StringKeys2) { z = "foo"; // error + const f: string = z; // ok } export {}; From 21f4f7ca8577018ccd5ddaf7b3ed0d634bb5e324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 20 Jan 2026 20:37:58 +0100 Subject: [PATCH 4/6] move the fix to `getApparentMappedTypeKeys` --- src/compiler/checker.ts | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8bd641b606e54..838d9efdd632e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23464,7 +23464,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function getApparentMappedTypeKeys(nameType: Type, mappedType: MappedType) { + function getApparentMappedTypeKeys(nameType: Type, mappedType: MappedType, forSource: boolean) { const modifiersType = getApparentType(getModifiersTypeFromMappedType(mappedType)); const mappedKeys: Type[] = []; forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType( @@ -23473,7 +23473,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { /*stringsOnly*/ false, t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(mappedType.mapper, getTypeParameterFromMappedType(mappedType), t))), ); - return getUnionType(mappedKeys); + const apparentKeys = getUnionType(mappedKeys); + if (forSource && apparentKeys.flags & TypeFlags.Never) { + // modifiers type of mapped type is often `unknown`, `keyof unknown` is `never` and that's assignable to everything + // letting this through is too permissive so we use the apparent type of an index type here instead + return stringNumberSymbolType; + } + return apparentKeys; } function structuredTypeRelatedToWorker(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, saveErrorInfo: ReturnType): Ternary { @@ -23657,7 +23663,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 = getApparentMappedTypeKeys(nameType, targetType, /*forSource*/ false); // 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]); } @@ -23864,18 +23870,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // 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. - let sourceMappedKeys: Type; - if (nameType && isMappedTypeWithKeyofConstraintDeclaration(mappedType)) { - sourceMappedKeys = getApparentMappedTypeKeys(nameType, mappedType); - if (sourceMappedKeys.flags & TypeFlags.Never) { - // modifiers type of mapped type is often `unknown`, `keyof unknown` is `never` and that's assignable to everything - // letting this through is too permissive so we use the apparent type of an index type here instead - sourceMappedKeys = stringNumberSymbolType; - } - } - else { - sourceMappedKeys = nameType || getConstraintTypeFromMappedType(mappedType); - } + const sourceMappedKeys = nameType && isMappedTypeWithKeyofConstraintDeclaration(mappedType) ? getApparentMappedTypeKeys(nameType, mappedType, /*forSource*/ true) : (nameType || getConstraintTypeFromMappedType(mappedType)); if (result = isRelatedTo(sourceMappedKeys, target, RecursionFlags.Source, reportErrors)) { return result; } From fcdaa913d5860b20fb73945b3c719db16b116f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 26 Jan 2026 15:58:44 +0100 Subject: [PATCH 5/6] remove `getApparentMappedTypeKeys` on the source side --- src/compiler/checker.ts | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 838d9efdd632e..7623bc35d5f65 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23464,22 +23464,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function getApparentMappedTypeKeys(nameType: Type, mappedType: MappedType, forSource: boolean) { - const modifiersType = getApparentType(getModifiersTypeFromMappedType(mappedType)); + function getApparentTargetMappedTypeKeys(nameType: Type, targetType: MappedType) { + const modifiersType = getApparentType(getModifiersTypeFromMappedType(targetType)); const mappedKeys: Type[] = []; forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType( modifiersType, TypeFlags.StringOrNumberLiteralOrUnique, /*stringsOnly*/ false, - t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(mappedType.mapper, getTypeParameterFromMappedType(mappedType), t))), + t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(targetType.mapper, getTypeParameterFromMappedType(targetType), t))), ); - const apparentKeys = getUnionType(mappedKeys); - if (forSource && apparentKeys.flags & TypeFlags.Never) { - // modifiers type of mapped type is often `unknown`, `keyof unknown` is `never` and that's assignable to everything - // letting this through is too permissive so we use the apparent type of an index type here instead - return stringNumberSymbolType; - } - return apparentKeys; + return getUnionType(mappedKeys); } function structuredTypeRelatedToWorker(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, saveErrorInfo: ReturnType): Ternary { @@ -23632,6 +23626,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. @@ -23663,7 +23663,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, /*forSource*/ false); + 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]); } @@ -23865,12 +23865,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, /*forSource*/ true) : (nameType || getConstraintTypeFromMappedType(mappedType)); + const sourceMappedKeys = nameType || getConstraintTypeFromMappedType(mappedType); if (result = isRelatedTo(sourceMappedKeys, target, RecursionFlags.Source, reportErrors)) { return result; } @@ -24117,7 +24112,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); } } From 73d96e1768e7e564d1559cce96351a244575b4b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 9 Feb 2026 11:28:15 +0100 Subject: [PATCH 6/6] fix index type constraints on mapped types with name types --- src/compiler/checker.ts | 11 +- .../keyRemappingKeyofResult3.errors.txt | 489 +++++++++++ .../keyRemappingKeyofResult3.symbols | 760 ++++++++++++++++++ .../reference/keyRemappingKeyofResult3.types | 703 ++++++++++++++++ .../compiler/keyRemappingKeyofResult3.ts | 204 +++++ 5 files changed, 2166 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/keyRemappingKeyofResult3.errors.txt create mode 100644 tests/baselines/reference/keyRemappingKeyofResult3.symbols create mode 100644 tests/baselines/reference/keyRemappingKeyofResult3.types create mode 100644 tests/cases/compiler/keyRemappingKeyofResult3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 95fdaf059678f..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; } /** 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/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 +}