mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-22 02:35:48 -05:00
Excess discriminated types match all discriminable properties (#32755)
* Target types in excess property checking must match all discriminable properties This allows fewer types to be discriminated in excess properties, which fixes some examples. * Add excess property test * Fix semicolon lint * Remove extra semicolon! * Improve EPC for unions with multiple discriminants
This commit is contained in:
committed by
GitHub
parent
b70f894881
commit
b24050aefd
@@ -14269,20 +14269,25 @@ namespace ts {
|
||||
function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary): Type | undefined;
|
||||
function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue: Type): Type;
|
||||
function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue?: Type) {
|
||||
let match: Type | undefined;
|
||||
// undefined=unknown, true=discriminated, false=not discriminated
|
||||
// The state of each type progresses from left to right. Discriminated types stop at 'true'.
|
||||
const discriminable = target.types.map(_ => undefined) as (boolean | undefined)[];
|
||||
for (const [getDiscriminatingType, propertyName] of discriminators) {
|
||||
let i = 0;
|
||||
for (const type of target.types) {
|
||||
const targetType = getTypeOfPropertyOfType(type, propertyName);
|
||||
if (targetType && related(getDiscriminatingType(), targetType)) {
|
||||
if (match) {
|
||||
if (type === match) continue; // Finding multiple fields which discriminate to the same type is fine
|
||||
return defaultValue;
|
||||
}
|
||||
match = type;
|
||||
discriminable[i] = discriminable[i] === undefined ? true : discriminable[i];
|
||||
}
|
||||
else {
|
||||
discriminable[i] = false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return match || defaultValue;
|
||||
const match = discriminable.indexOf(/*searchElement*/ true);
|
||||
// make sure exactly 1 matches before returning it
|
||||
return match === -1 || discriminable.indexOf(/*searchElement*/ true, match + 1) !== -1 ? defaultValue : target.types[match];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user