Fix discriminant property check

This commit is contained in:
Anders Hejlsberg
2018-12-20 07:17:42 -08:00
parent 08022d57c8
commit 93acaac087
2 changed files with 30 additions and 36 deletions

View File

@@ -7669,38 +7669,37 @@ namespace ts {
return props[0];
}
let declarations: Declaration[] | undefined;
let commonType: Type | undefined;
let firstType: Type | undefined;
let nameType: Type | undefined;
const propTypes: Type[] = [];
let first = true;
let commonValueDeclaration: Declaration | undefined;
let firstValueDeclaration: Declaration | undefined;
let hasNonUniformValueDeclaration = false;
for (const prop of props) {
if (!commonValueDeclaration) {
commonValueDeclaration = prop.valueDeclaration;
if (!firstValueDeclaration) {
firstValueDeclaration = prop.valueDeclaration;
}
else if (prop.valueDeclaration !== commonValueDeclaration) {
else if (prop.valueDeclaration !== firstValueDeclaration) {
hasNonUniformValueDeclaration = true;
}
declarations = addRange(declarations, prop.declarations);
const type = getTypeOfSymbol(prop);
if (first) {
commonType = type;
if (!firstType) {
firstType = type;
nameType = prop.nameType;
first = false;
}
else {
if (type !== commonType) {
checkFlags |= CheckFlags.HasNonUniformType;
}
else if (type !== firstType) {
checkFlags |= CheckFlags.HasNonUniformType;
}
if (isLiteralType(type)) {
checkFlags |= CheckFlags.HasLiteralType;
}
propTypes.push(type);
}
addRange(propTypes, indexTypes);
const result = createSymbol(SymbolFlags.Property | commonFlags, name, syntheticFlag | checkFlags);
result.containingType = containingType;
if (!hasNonUniformValueDeclaration && commonValueDeclaration) {
result.valueDeclaration = commonValueDeclaration;
if (!hasNonUniformValueDeclaration && firstValueDeclaration) {
result.valueDeclaration = firstValueDeclaration;
}
result.declarations = declarations!;
result.nameType = nameType;
@@ -14814,17 +14813,8 @@ namespace ts {
}
function isDiscriminantType(type: Type): boolean {
if (type.flags & TypeFlags.Union) {
if (type.flags & (TypeFlags.Boolean | TypeFlags.EnumLiteral)) {
return true;
}
let combined = 0;
for (const t of (<UnionType>type).types) combined |= t.flags;
if (combined & TypeFlags.Unit && !(combined & TypeFlags.Instantiable)) {
return true;
}
}
return false;
return !!(type.flags & TypeFlags.Union &&
(type.flags & (TypeFlags.Boolean | TypeFlags.EnumLiteral) || !isGenericIndexType(type)));
}
function isDiscriminantProperty(type: Type | undefined, name: __String) {
@@ -14832,7 +14822,9 @@ namespace ts {
const prop = getUnionOrIntersectionProperty(<UnionType>type, name);
if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) {
if ((<TransientSymbol>prop).isDiscriminantProperty === undefined) {
(<TransientSymbol>prop).isDiscriminantProperty = !!((<TransientSymbol>prop).checkFlags & CheckFlags.HasNonUniformType) && isDiscriminantType(getTypeOfSymbol(prop));
(<TransientSymbol>prop).isDiscriminantProperty =
((<TransientSymbol>prop).checkFlags & CheckFlags.Discriminant) === CheckFlags.Discriminant &&
isDiscriminantType(getTypeOfSymbol(prop));
}
return !!(<TransientSymbol>prop).isDiscriminantProperty;
}

View File

@@ -3677,15 +3677,17 @@ namespace ts {
Readonly = 1 << 3, // Readonly transient symbol
Partial = 1 << 4, // Synthetic property present in some but not all constituents
HasNonUniformType = 1 << 5, // Synthetic property with non-uniform type in constituents
ContainsPublic = 1 << 6, // Synthetic property with public constituent(s)
ContainsProtected = 1 << 7, // Synthetic property with protected constituent(s)
ContainsPrivate = 1 << 8, // Synthetic property with private constituent(s)
ContainsStatic = 1 << 9, // Synthetic property with static constituent(s)
Late = 1 << 10, // Late-bound symbol for a computed property with a dynamic name
ReverseMapped = 1 << 11, // Property of reverse-inferred homomorphic mapped type
OptionalParameter = 1 << 12, // Optional parameter
RestParameter = 1 << 13, // Rest parameter
Synthetic = SyntheticProperty | SyntheticMethod
HasLiteralType = 1 << 6, // Synthetic property with at least one literal type in constituents
ContainsPublic = 1 << 7, // Synthetic property with public constituent(s)
ContainsProtected = 1 << 8, // Synthetic property with protected constituent(s)
ContainsPrivate = 1 << 9, // Synthetic property with private constituent(s)
ContainsStatic = 1 << 10, // Synthetic property with static constituent(s)
Late = 1 << 11, // Late-bound symbol for a computed property with a dynamic name
ReverseMapped = 1 << 12, // Property of reverse-inferred homomorphic mapped type
OptionalParameter = 1 << 13, // Optional parameter
RestParameter = 1 << 14, // Rest parameter
Synthetic = SyntheticProperty | SyntheticMethod,
Discriminant = HasNonUniformType | HasLiteralType
}
/* @internal */