-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Fixed const reverse mapped types themselves to be treated as const #55794
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
//// [tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterConstModifiersReverseMappedTypes.ts] //// | ||
|
||
=== typeParameterConstModifiersReverseMappedTypes.ts === | ||
declare function test1<const T>(obj: { | ||
>test1 : Symbol(test1, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 0, 0)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 0, 23)) | ||
>obj : Symbol(obj, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 0, 32)) | ||
|
||
[K in keyof T]: T[K]; | ||
>K : Symbol(K, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 1, 3)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 0, 23)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 0, 23)) | ||
>K : Symbol(K, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 1, 3)) | ||
|
||
}): [T, typeof obj]; | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 0, 23)) | ||
>obj : Symbol(obj, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 0, 32)) | ||
|
||
const result1 = test1({ | ||
>result1 : Symbol(result1, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 4, 5)) | ||
>test1 : Symbol(test1, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 0, 0)) | ||
|
||
prop: "foo", | ||
>prop : Symbol(prop, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 4, 23)) | ||
|
||
nested: { | ||
>nested : Symbol(nested, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 5, 14)) | ||
|
||
nestedProp: "bar", | ||
>nestedProp : Symbol(nestedProp, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 6, 11)) | ||
|
||
}, | ||
}); | ||
|
||
declare function test2<const T>(obj: { | ||
>test2 : Symbol(test2, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 9, 3)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 11, 23)) | ||
>obj : Symbol(obj, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 11, 32)) | ||
|
||
readonly [K in keyof T]: T[K]; | ||
>K : Symbol(K, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 12, 12)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 11, 23)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 11, 23)) | ||
>K : Symbol(K, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 12, 12)) | ||
|
||
}): [T, typeof obj]; | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 11, 23)) | ||
>obj : Symbol(obj, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 11, 32)) | ||
|
||
const result2 = test2({ | ||
>result2 : Symbol(result2, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 15, 5)) | ||
>test2 : Symbol(test2, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 9, 3)) | ||
|
||
prop: "foo", | ||
>prop : Symbol(prop, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 15, 23)) | ||
|
||
nested: { | ||
>nested : Symbol(nested, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 16, 14)) | ||
|
||
nestedProp: "bar", | ||
>nestedProp : Symbol(nestedProp, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 17, 11)) | ||
|
||
}, | ||
}); | ||
|
||
declare function test3<const T>(obj: { | ||
>test3 : Symbol(test3, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 20, 3)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 22, 23)) | ||
>obj : Symbol(obj, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 22, 32)) | ||
|
||
-readonly [K in keyof T]: T[K]; | ||
>K : Symbol(K, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 23, 13)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 22, 23)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 22, 23)) | ||
>K : Symbol(K, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 23, 13)) | ||
|
||
}): [T, typeof obj]; | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 22, 23)) | ||
>obj : Symbol(obj, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 22, 32)) | ||
|
||
const result3 = test3({ | ||
>result3 : Symbol(result3, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 26, 5)) | ||
>test3 : Symbol(test3, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 20, 3)) | ||
|
||
prop: "foo", | ||
>prop : Symbol(prop, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 26, 23)) | ||
|
||
nested: { | ||
>nested : Symbol(nested, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 27, 14)) | ||
|
||
nestedProp: "bar", | ||
>nestedProp : Symbol(nestedProp, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 28, 11)) | ||
|
||
}, | ||
}); | ||
|
||
declare function test4<const T extends readonly unknown[]>(arr: { | ||
>test4 : Symbol(test4, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 31, 3)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 33, 23)) | ||
>arr : Symbol(arr, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 33, 59)) | ||
|
||
[K in keyof T]: T[K]; | ||
>K : Symbol(K, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 34, 3)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 33, 23)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 33, 23)) | ||
>K : Symbol(K, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 34, 3)) | ||
|
||
}): T; | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 33, 23)) | ||
|
||
const result4 = test4(["1", 2]); | ||
>result4 : Symbol(result4, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 37, 5)) | ||
>test4 : Symbol(test4, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 31, 3)) | ||
|
||
declare function test5<const T extends readonly unknown[]>( | ||
>test5 : Symbol(test5, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 37, 32)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 39, 23)) | ||
|
||
...args: { | ||
>args : Symbol(args, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 39, 59)) | ||
|
||
[K in keyof T]: T[K]; | ||
>K : Symbol(K, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 41, 5)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 39, 23)) | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 39, 23)) | ||
>K : Symbol(K, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 41, 5)) | ||
} | ||
): T; | ||
>T : Symbol(T, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 39, 23)) | ||
|
||
const result5 = test5({ a: "foo" }); | ||
>result5 : Symbol(result5, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 45, 5)) | ||
>test5 : Symbol(test5, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 37, 32)) | ||
>a : Symbol(a, Decl(typeParameterConstModifiersReverseMappedTypes.ts, 45, 23)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
//// [tests/cases/conformance/types/typeParameters/typeParameterLists/typeParameterConstModifiersReverseMappedTypes.ts] //// | ||
|
||
=== typeParameterConstModifiersReverseMappedTypes.ts === | ||
declare function test1<const T>(obj: { | ||
>test1 : <const T>(obj: { [K in keyof T]: T[K]; }) => [T, typeof obj] | ||
>obj : { [K in keyof T]: T[K]; } | ||
|
||
[K in keyof T]: T[K]; | ||
}): [T, typeof obj]; | ||
>obj : { [K in keyof T]: T[K]; } | ||
|
||
const result1 = test1({ | ||
>result1 : [{ readonly prop: "foo"; readonly nested: { readonly nestedProp: "bar"; }; }, { readonly prop: "foo"; readonly nested: { readonly nestedProp: "bar"; }; }] | ||
>test1({ prop: "foo", nested: { nestedProp: "bar", },}) : [{ readonly prop: "foo"; readonly nested: { readonly nestedProp: "bar"; }; }, { readonly prop: "foo"; readonly nested: { readonly nestedProp: "bar"; }; }] | ||
>test1 : <const T>(obj: { [K in keyof T]: T[K]; }) => [T, { [K in keyof T]: T[K]; }] | ||
>{ prop: "foo", nested: { nestedProp: "bar", },} : { prop: "foo"; nested: { nestedProp: "bar"; }; } | ||
|
||
prop: "foo", | ||
>prop : "foo" | ||
>"foo" : "foo" | ||
|
||
nested: { | ||
>nested : { nestedProp: "bar"; } | ||
>{ nestedProp: "bar", } : { nestedProp: "bar"; } | ||
|
||
nestedProp: "bar", | ||
>nestedProp : "bar" | ||
>"bar" : "bar" | ||
|
||
}, | ||
}); | ||
|
||
declare function test2<const T>(obj: { | ||
>test2 : <const T>(obj: { readonly [K in keyof T]: T[K]; }) => [T, typeof obj] | ||
>obj : { readonly [K in keyof T]: T[K]; } | ||
|
||
readonly [K in keyof T]: T[K]; | ||
}): [T, typeof obj]; | ||
>obj : { readonly [K in keyof T]: T[K]; } | ||
|
||
const result2 = test2({ | ||
>result2 : [{ prop: "foo"; nested: { readonly nestedProp: "bar"; }; }, { readonly prop: "foo"; readonly nested: { readonly nestedProp: "bar"; }; }] | ||
>test2({ prop: "foo", nested: { nestedProp: "bar", },}) : [{ prop: "foo"; nested: { readonly nestedProp: "bar"; }; }, { readonly prop: "foo"; readonly nested: { readonly nestedProp: "bar"; }; }] | ||
>test2 : <const T>(obj: { readonly [K in keyof T]: T[K]; }) => [T, { readonly [K in keyof T]: T[K]; }] | ||
>{ prop: "foo", nested: { nestedProp: "bar", },} : { prop: "foo"; nested: { nestedProp: "bar"; }; } | ||
|
||
prop: "foo", | ||
>prop : "foo" | ||
>"foo" : "foo" | ||
|
||
nested: { | ||
>nested : { nestedProp: "bar"; } | ||
>{ nestedProp: "bar", } : { nestedProp: "bar"; } | ||
|
||
nestedProp: "bar", | ||
>nestedProp : "bar" | ||
>"bar" : "bar" | ||
|
||
}, | ||
}); | ||
|
||
declare function test3<const T>(obj: { | ||
>test3 : <const T>(obj: { -readonly [K in keyof T]: T[K]; }) => [T, typeof obj] | ||
>obj : { -readonly [K in keyof T]: T[K]; } | ||
|
||
-readonly [K in keyof T]: T[K]; | ||
}): [T, typeof obj]; | ||
>obj : { -readonly [K in keyof T]: T[K]; } | ||
|
||
const result3 = test3({ | ||
>result3 : [{ readonly prop: "foo"; readonly nested: { readonly nestedProp: "bar"; }; }, { prop: "foo"; nested: { readonly nestedProp: "bar"; }; }] | ||
>test3({ prop: "foo", nested: { nestedProp: "bar", },}) : [{ readonly prop: "foo"; readonly nested: { readonly nestedProp: "bar"; }; }, { prop: "foo"; nested: { readonly nestedProp: "bar"; }; }] | ||
>test3 : <const T>(obj: { -readonly [K in keyof T]: T[K]; }) => [T, { -readonly [K in keyof T]: T[K]; }] | ||
>{ prop: "foo", nested: { nestedProp: "bar", },} : { prop: "foo"; nested: { nestedProp: "bar"; }; } | ||
|
||
prop: "foo", | ||
>prop : "foo" | ||
>"foo" : "foo" | ||
|
||
nested: { | ||
>nested : { nestedProp: "bar"; } | ||
>{ nestedProp: "bar", } : { nestedProp: "bar"; } | ||
|
||
nestedProp: "bar", | ||
>nestedProp : "bar" | ||
>"bar" : "bar" | ||
|
||
}, | ||
}); | ||
|
||
declare function test4<const T extends readonly unknown[]>(arr: { | ||
>test4 : <const T extends readonly unknown[]>(arr: { [K in keyof T]: T[K]; }) => T | ||
>arr : { [K in keyof T]: T[K]; } | ||
|
||
[K in keyof T]: T[K]; | ||
}): T; | ||
|
||
const result4 = test4(["1", 2]); | ||
>result4 : readonly ["1", 2] | ||
>test4(["1", 2]) : readonly ["1", 2] | ||
>test4 : <const T extends readonly unknown[]>(arr: { [K in keyof T]: T[K]; }) => T | ||
>["1", 2] : ["1", 2] | ||
>"1" : "1" | ||
>2 : 2 | ||
|
||
declare function test5<const T extends readonly unknown[]>( | ||
>test5 : <const T extends readonly unknown[]>(...args: { [K in keyof T]: T[K]; }) => T | ||
|
||
...args: { | ||
>args : { [K in keyof T]: T[K]; } | ||
|
||
[K in keyof T]: T[K]; | ||
} | ||
): T; | ||
|
||
const result5 = test5({ a: "foo" }); | ||
>result5 : readonly [{ readonly a: "foo"; }] | ||
>test5({ a: "foo" }) : readonly [{ readonly a: "foo"; }] | ||
>test5 : <const T extends readonly unknown[]>(...args: { [K in keyof T]: T[K]; }) => T | ||
>{ a: "foo" } : { a: "foo"; } | ||
>a : "foo" | ||
>"foo" : "foo" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// @strict: true | ||
// @noEmit: true | ||
|
||
declare function test1<const T>(obj: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The first 3 test cases are testing objects and how Those objects today would be constified for the most part but their properties wouldn't always be marked as |
||
[K in keyof T]: T[K]; | ||
}): [T, typeof obj]; | ||
|
||
const result1 = test1({ | ||
prop: "foo", | ||
nested: { | ||
nestedProp: "bar", | ||
}, | ||
}); | ||
|
||
declare function test2<const T>(obj: { | ||
readonly [K in keyof T]: T[K]; | ||
}): [T, typeof obj]; | ||
|
||
const result2 = test2({ | ||
prop: "foo", | ||
nested: { | ||
nestedProp: "bar", | ||
}, | ||
}); | ||
|
||
declare function test3<const T>(obj: { | ||
-readonly [K in keyof T]: T[K]; | ||
}): [T, typeof obj]; | ||
|
||
const result3 = test3({ | ||
prop: "foo", | ||
nested: { | ||
nestedProp: "bar", | ||
}, | ||
}); | ||
|
||
declare function test4<const T extends readonly unknown[]>(arr: { | ||
[K in keyof T]: T[K]; | ||
}): T; | ||
|
||
const result4 = test4(["1", 2]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an especially important part of the fix. Currently |
||
|
||
declare function test5<const T extends readonly unknown[]>( | ||
...args: { | ||
[K in keyof T]: T[K]; | ||
} | ||
): T; | ||
|
||
const result5 = test5({ a: "foo" }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are also some other test cases that I'd like to add here but I'm not entirely sure what should be the expected results for them
const T, P extends keyof T
- this might iterate overP
which might be the subset ofkeyof T
. Should we still assign constness toT
in such a case? See the playground TS playground. Note that it's not really possible to gatherP
across from different mapped types and somehow different mapped type to build up a "combined" reverse mapped type: TS playgroundK in keyof T | "extra"
- what should happen with a non-homomorphic case like this? TS playgroundThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const
type variables, but if they're in-use, there a strong signal that const-ness is desired somewhere related to that type parameter. The workflow is usually "does this do what I want? No? Add aconst
.", so theconst
normally only gets added by people if it's meant to be meaningful to inference.