Add inference priority for mapped type keys (#22246)
* Add inference priority for mapped type keys The new priority causes union inference, similarly to return type * Rename priority * Fix comment typo
This commit is contained in:
parent
2ac2291b84
commit
53ae507545
|
@ -11789,7 +11789,7 @@ namespace ts {
|
|||
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target);
|
||||
if (inferredType) {
|
||||
const savePriority = priority;
|
||||
priority |= InferencePriority.MappedType;
|
||||
priority |= InferencePriority.HomomorphicMappedType;
|
||||
inferFromTypes(inferredType, inference.typeParameter);
|
||||
priority = savePriority;
|
||||
}
|
||||
|
@ -11799,7 +11799,10 @@ namespace ts {
|
|||
if (constraintType.flags & TypeFlags.TypeParameter) {
|
||||
// We're inferring from some source type S to a mapped type { [P in T]: X }, where T is a type
|
||||
// parameter. Infer from 'keyof S' to T and infer from a union of each property type in S to X.
|
||||
const savePriority = priority;
|
||||
priority |= InferencePriority.MappedTypeConstraint;
|
||||
inferFromTypes(getIndexType(source), constraintType);
|
||||
priority = savePriority;
|
||||
inferFromTypes(getUnionType(map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(<MappedType>target));
|
||||
return;
|
||||
}
|
||||
|
@ -11932,7 +11935,7 @@ namespace ts {
|
|||
// If all inferences were made from contravariant positions, infer a common subtype. Otherwise, if
|
||||
// union types were requested or if all inferences were made from the return type position, infer a
|
||||
// union type. Otherwise, infer a common supertype.
|
||||
const unwidenedType = context.flags & InferenceFlags.InferUnionTypes || inference.priority & InferencePriority.ReturnType ?
|
||||
const unwidenedType = context.flags & InferenceFlags.InferUnionTypes || inference.priority & InferencePriority.PriorityImpliesUnion ?
|
||||
getUnionType(baseCandidates, UnionReduction.Subtype) :
|
||||
getCommonSupertype(baseCandidates);
|
||||
inferredType = getWidenedType(unwidenedType);
|
||||
|
|
|
@ -3919,11 +3919,14 @@ namespace ts {
|
|||
export type TypeMapper = (t: TypeParameter) => Type;
|
||||
|
||||
export const enum InferencePriority {
|
||||
NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type
|
||||
MappedType = 1 << 1, // Reverse inference for mapped type
|
||||
ReturnType = 1 << 2, // Inference made from return type of generic function
|
||||
NoConstraints = 1 << 3, // Don't infer from constraints of instantiable types
|
||||
AlwaysStrict = 1 << 4, // Always use strict rules for contravariant inferences
|
||||
NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type
|
||||
HomomorphicMappedType = 1 << 1, // Reverse inference for homomorphic mapped type
|
||||
MappedTypeConstraint = 1 << 2, // Reverse inference for mapped type
|
||||
ReturnType = 1 << 3, // Inference made from return type of generic function
|
||||
NoConstraints = 1 << 4, // Don't infer from constraints of instantiable types
|
||||
AlwaysStrict = 1 << 5, // Always use strict rules for contravariant inferences
|
||||
|
||||
PriorityImpliesUnion = ReturnType | MappedTypeConstraint, // These priorities imply that the resulting type should be a union of all candidates
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
|
|
@ -2236,10 +2236,12 @@ declare namespace ts {
|
|||
}
|
||||
enum InferencePriority {
|
||||
NakedTypeVariable = 1,
|
||||
MappedType = 2,
|
||||
ReturnType = 4,
|
||||
NoConstraints = 8,
|
||||
AlwaysStrict = 16,
|
||||
HomomorphicMappedType = 2,
|
||||
MappedTypeConstraint = 4,
|
||||
ReturnType = 8,
|
||||
NoConstraints = 16,
|
||||
AlwaysStrict = 32,
|
||||
PriorityImpliesUnion = 12,
|
||||
}
|
||||
interface JsFileExtensionInfo {
|
||||
extension: string;
|
||||
|
|
10
tests/baselines/reference/api/typescript.d.ts
vendored
10
tests/baselines/reference/api/typescript.d.ts
vendored
|
@ -2236,10 +2236,12 @@ declare namespace ts {
|
|||
}
|
||||
enum InferencePriority {
|
||||
NakedTypeVariable = 1,
|
||||
MappedType = 2,
|
||||
ReturnType = 4,
|
||||
NoConstraints = 8,
|
||||
AlwaysStrict = 16,
|
||||
HomomorphicMappedType = 2,
|
||||
MappedTypeConstraint = 4,
|
||||
ReturnType = 8,
|
||||
NoConstraints = 16,
|
||||
AlwaysStrict = 32,
|
||||
PriorityImpliesUnion = 12,
|
||||
}
|
||||
interface JsFileExtensionInfo {
|
||||
extension: string;
|
||||
|
|
34
tests/baselines/reference/mappedTypeMultiInference.js
Normal file
34
tests/baselines/reference/mappedTypeMultiInference.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
//// [mappedTypeMultiInference.ts]
|
||||
interface Style {
|
||||
flashy: any;
|
||||
}
|
||||
|
||||
declare function mergeStyleSets<K extends string>(
|
||||
...cssSets: { [P in K]?: Style }[]): { [P in K]: Style };
|
||||
|
||||
// Expected:
|
||||
// let x: {
|
||||
// a: Style;
|
||||
// b: Style;
|
||||
// }
|
||||
let x = mergeStyleSets(
|
||||
{},
|
||||
{
|
||||
a: { flashy: true },
|
||||
},
|
||||
{
|
||||
b: { flashy: true },
|
||||
},
|
||||
)
|
||||
|
||||
//// [mappedTypeMultiInference.js]
|
||||
// Expected:
|
||||
// let x: {
|
||||
// a: Style;
|
||||
// b: Style;
|
||||
// }
|
||||
var x = mergeStyleSets({}, {
|
||||
a: { flashy: true }
|
||||
}, {
|
||||
b: { flashy: true }
|
||||
});
|
44
tests/baselines/reference/mappedTypeMultiInference.symbols
Normal file
44
tests/baselines/reference/mappedTypeMultiInference.symbols
Normal file
|
@ -0,0 +1,44 @@
|
|||
=== tests/cases/compiler/mappedTypeMultiInference.ts ===
|
||||
interface Style {
|
||||
>Style : Symbol(Style, Decl(mappedTypeMultiInference.ts, 0, 0))
|
||||
|
||||
flashy: any;
|
||||
>flashy : Symbol(Style.flashy, Decl(mappedTypeMultiInference.ts, 0, 17))
|
||||
}
|
||||
|
||||
declare function mergeStyleSets<K extends string>(
|
||||
>mergeStyleSets : Symbol(mergeStyleSets, Decl(mappedTypeMultiInference.ts, 2, 1))
|
||||
>K : Symbol(K, Decl(mappedTypeMultiInference.ts, 4, 32))
|
||||
|
||||
...cssSets: { [P in K]?: Style }[]): { [P in K]: Style };
|
||||
>cssSets : Symbol(cssSets, Decl(mappedTypeMultiInference.ts, 4, 50))
|
||||
>P : Symbol(P, Decl(mappedTypeMultiInference.ts, 5, 19))
|
||||
>K : Symbol(K, Decl(mappedTypeMultiInference.ts, 4, 32))
|
||||
>Style : Symbol(Style, Decl(mappedTypeMultiInference.ts, 0, 0))
|
||||
>P : Symbol(P, Decl(mappedTypeMultiInference.ts, 5, 44))
|
||||
>K : Symbol(K, Decl(mappedTypeMultiInference.ts, 4, 32))
|
||||
>Style : Symbol(Style, Decl(mappedTypeMultiInference.ts, 0, 0))
|
||||
|
||||
// Expected:
|
||||
// let x: {
|
||||
// a: Style;
|
||||
// b: Style;
|
||||
// }
|
||||
let x = mergeStyleSets(
|
||||
>x : Symbol(x, Decl(mappedTypeMultiInference.ts, 12, 3))
|
||||
>mergeStyleSets : Symbol(mergeStyleSets, Decl(mappedTypeMultiInference.ts, 2, 1))
|
||||
|
||||
{},
|
||||
{
|
||||
a: { flashy: true },
|
||||
>a : Symbol(a, Decl(mappedTypeMultiInference.ts, 14, 5))
|
||||
>flashy : Symbol(flashy, Decl(mappedTypeMultiInference.ts, 15, 12))
|
||||
|
||||
},
|
||||
{
|
||||
b: { flashy: true },
|
||||
>b : Symbol(b, Decl(mappedTypeMultiInference.ts, 17, 5))
|
||||
>flashy : Symbol(flashy, Decl(mappedTypeMultiInference.ts, 18, 12))
|
||||
|
||||
},
|
||||
)
|
54
tests/baselines/reference/mappedTypeMultiInference.types
Normal file
54
tests/baselines/reference/mappedTypeMultiInference.types
Normal file
|
@ -0,0 +1,54 @@
|
|||
=== tests/cases/compiler/mappedTypeMultiInference.ts ===
|
||||
interface Style {
|
||||
>Style : Style
|
||||
|
||||
flashy: any;
|
||||
>flashy : any
|
||||
}
|
||||
|
||||
declare function mergeStyleSets<K extends string>(
|
||||
>mergeStyleSets : <K extends string>(...cssSets: { [P in K]?: Style; }[]) => { [P in K]: Style; }
|
||||
>K : K
|
||||
|
||||
...cssSets: { [P in K]?: Style }[]): { [P in K]: Style };
|
||||
>cssSets : { [P in K]?: Style; }[]
|
||||
>P : P
|
||||
>K : K
|
||||
>Style : Style
|
||||
>P : P
|
||||
>K : K
|
||||
>Style : Style
|
||||
|
||||
// Expected:
|
||||
// let x: {
|
||||
// a: Style;
|
||||
// b: Style;
|
||||
// }
|
||||
let x = mergeStyleSets(
|
||||
>x : { a: Style; b: Style; }
|
||||
>mergeStyleSets( {}, { a: { flashy: true }, }, { b: { flashy: true }, },) : { a: Style; b: Style; }
|
||||
>mergeStyleSets : <K extends string>(...cssSets: { [P in K]?: Style; }[]) => { [P in K]: Style; }
|
||||
|
||||
{},
|
||||
>{} : {}
|
||||
{
|
||||
>{ a: { flashy: true }, } : { a: { flashy: boolean; }; }
|
||||
|
||||
a: { flashy: true },
|
||||
>a : { flashy: boolean; }
|
||||
>{ flashy: true } : { flashy: boolean; }
|
||||
>flashy : boolean
|
||||
>true : true
|
||||
|
||||
},
|
||||
{
|
||||
>{ b: { flashy: true }, } : { b: { flashy: boolean; }; }
|
||||
|
||||
b: { flashy: true },
|
||||
>b : { flashy: boolean; }
|
||||
>{ flashy: true } : { flashy: boolean; }
|
||||
>flashy : boolean
|
||||
>true : true
|
||||
|
||||
},
|
||||
)
|
21
tests/cases/compiler/mappedTypeMultiInference.ts
Normal file
21
tests/cases/compiler/mappedTypeMultiInference.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
interface Style {
|
||||
flashy: any;
|
||||
}
|
||||
|
||||
declare function mergeStyleSets<K extends string>(
|
||||
...cssSets: { [P in K]?: Style }[]): { [P in K]: Style };
|
||||
|
||||
// Expected:
|
||||
// let x: {
|
||||
// a: Style;
|
||||
// b: Style;
|
||||
// }
|
||||
let x = mergeStyleSets(
|
||||
{},
|
||||
{
|
||||
a: { flashy: true },
|
||||
},
|
||||
{
|
||||
b: { flashy: true },
|
||||
},
|
||||
)
|
Loading…
Reference in a new issue