mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-17 00:34:47 -05:00
Support unions/intersections in spread types
1. Lift unions and intersections above spread types when creating them in getSpreadType. 2. Cleanup now-unneeded changes to existing union/intersection code. 3. Cleanup some incorrect errors I added earlier.
This commit is contained in:
@@ -2197,7 +2197,7 @@ namespace ts {
|
||||
writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags);
|
||||
}
|
||||
else if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
writeUnionOrIntersectionType(<TypeOperatorType>type, nextFlags);
|
||||
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Spread) {
|
||||
writeSpreadType(<SpreadType>type, nextFlags);
|
||||
@@ -2291,7 +2291,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function writeUnionOrIntersectionType(type: TypeOperatorType, flags: TypeFormatFlags) {
|
||||
function writeUnionOrIntersectionType(type: UnionOrIntersectionType, flags: TypeFormatFlags) {
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
}
|
||||
@@ -4449,7 +4449,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getPropertiesOfUnionOrIntersectionType(type: TypeOperatorType): Symbol[] {
|
||||
function getPropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType): Symbol[] {
|
||||
for (const current of type.types) {
|
||||
for (const prop of getPropertiesOfType(current)) {
|
||||
getUnionOrIntersectionProperty(type, prop.name);
|
||||
@@ -4499,7 +4499,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getApparentTypeOfSpread(type: SpreadType) {
|
||||
return getSpreadType([getApparentType(type.left), getApparentType(type.right)], type.symbol, undefined, undefined);
|
||||
return getSpreadType([getApparentType(type.left), getApparentType(type.right)], type.symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4529,44 +4529,35 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function createUnionOrIntersectionProperty(containingType: TypeOperatorType, name: string): Symbol {
|
||||
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string) {
|
||||
const types = containingType.types;
|
||||
return createUnionOrIntersectionOrSpreadPropertySymbol(containingType, name, () => {
|
||||
let props: Symbol[];
|
||||
// Flags we want to propagate to the result if they exist in all source symbols
|
||||
let commonFlags = (containingType.flags & TypeFlags.Intersection) ? SymbolFlags.Optional : SymbolFlags.None;
|
||||
let isReadonly = false;
|
||||
let isPartial = false;
|
||||
for (const current of types) {
|
||||
const type = getApparentType(current);
|
||||
if (type !== unknownType) {
|
||||
const prop = getPropertyOfType(type, name);
|
||||
if (prop && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected))) {
|
||||
commonFlags &= prop.flags;
|
||||
if (!props) {
|
||||
props = [prop];
|
||||
}
|
||||
else if (!contains(props, prop)) {
|
||||
props.push(prop);
|
||||
}
|
||||
if (isReadonlySymbol(prop)) {
|
||||
isReadonly = true;
|
||||
}
|
||||
let props: Symbol[];
|
||||
// Flags we want to propagate to the result if they exist in all source symbols
|
||||
let commonFlags = (containingType.flags & TypeFlags.Intersection) ? SymbolFlags.Optional : SymbolFlags.None;
|
||||
let isReadonly = false;
|
||||
let isPartial = false;
|
||||
for (const current of types) {
|
||||
const type = getApparentType(current);
|
||||
if (type !== unknownType) {
|
||||
const prop = getPropertyOfType(type, name);
|
||||
if (prop && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected))) {
|
||||
commonFlags &= prop.flags;
|
||||
if (!props) {
|
||||
props = [prop];
|
||||
}
|
||||
else if (!contains(props, prop)) {
|
||||
props.push(prop);
|
||||
}
|
||||
if (isReadonlySymbol(prop)) {
|
||||
isReadonly = true;
|
||||
}
|
||||
|
||||
}
|
||||
else if (containingType.flags & TypeFlags.Union) {
|
||||
isPartial = true;
|
||||
}
|
||||
}
|
||||
else if (containingType.flags & TypeFlags.Union) {
|
||||
isPartial = true;
|
||||
}
|
||||
}
|
||||
return [props, isReadonly, isPartial, commonFlags];
|
||||
});
|
||||
}
|
||||
|
||||
function createUnionOrIntersectionOrSpreadPropertySymbol(containingType: TypeOperatorType,
|
||||
name: string,
|
||||
symbolCreator: () => [Symbol[], boolean, boolean, SymbolFlags]) {
|
||||
const [props, isReadonly, isPartial, flags] = symbolCreator();
|
||||
}
|
||||
if (!props) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -4590,7 +4581,7 @@ namespace ts {
|
||||
}
|
||||
propTypes.push(type);
|
||||
}
|
||||
const result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | flags, name);
|
||||
const result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | commonFlags, name);
|
||||
result.syntheticKind === SyntheticSymbolKind.UnionOrIntersection;
|
||||
result.containingType = containingType;
|
||||
result.hasNonUniformType = hasNonUniformType;
|
||||
@@ -4609,7 +4600,7 @@ namespace ts {
|
||||
// constituents, in which case the isPartial flag is set when the containing type is union type. We need
|
||||
// these partial properties when identifying discriminant properties, but otherwise they are filtered out
|
||||
// and do not appear to be present in the union type.
|
||||
function getUnionOrIntersectionProperty(type: TypeOperatorType, name: string): Symbol {
|
||||
function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: string): Symbol {
|
||||
const properties = type.resolvedProperties || (type.resolvedProperties = createMap<Symbol>());
|
||||
let property = properties[name];
|
||||
if (!property) {
|
||||
@@ -4621,7 +4612,7 @@ namespace ts {
|
||||
return property;
|
||||
}
|
||||
|
||||
function getPropertyOfUnionOrIntersectionType(type: TypeOperatorType, name: string): Symbol {
|
||||
function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: string): Symbol {
|
||||
const property = getUnionOrIntersectionProperty(type, name);
|
||||
// We need to filter out partial properties in union types
|
||||
return property && !(property.flags & SymbolFlags.SyntheticProperty && (<TransientSymbol>property).isPartial) ? property : undefined;
|
||||
@@ -4652,7 +4643,7 @@ namespace ts {
|
||||
return getPropertyOfObjectType(globalObjectType, name);
|
||||
}
|
||||
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
return getPropertyOfUnionOrIntersectionType(<TypeOperatorType>type, name);
|
||||
return getPropertyOfUnionOrIntersectionType(<UnionOrIntersectionType>type, name);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -5773,6 +5764,9 @@ namespace ts {
|
||||
return spreadTypes[id];
|
||||
}
|
||||
const right = types.pop();
|
||||
if (right.flags & TypeFlags.Any) {
|
||||
return anyType;
|
||||
}
|
||||
if (right.flags & TypeFlags.Spread) {
|
||||
// spread is right associative and associativity applies, so transform
|
||||
// (T ... U) ... V to T ... (U ... V)
|
||||
@@ -5783,9 +5777,22 @@ namespace ts {
|
||||
types.push(rspread.right);
|
||||
return getSpreadType(types, symbol, aliasSymbol, aliasTypeArguments);
|
||||
}
|
||||
if (right.flags & TypeFlags.Intersection) {
|
||||
const spreads = map((right as IntersectionType).types,
|
||||
t => getSpreadType(types.slice().concat([t]), symbol, aliasSymbol, aliasTypeArguments));
|
||||
return getIntersectionType(spreads, aliasSymbol, aliasTypeArguments);
|
||||
}
|
||||
if (right.flags & TypeFlags.Union) {
|
||||
// TODO: types is mutable, so this block has to happen before the call to `const left = getSpreadType(...)`
|
||||
// because that call consumes the array. It might be worthwhile to use a simple linked list here instead.
|
||||
// It would avoid the slice+concat call that is needed here for multiple calls to getSpreadType.
|
||||
const spreads = map((right as UnionType).types,
|
||||
t => getSpreadType(types.slice().concat([t]), symbol, aliasSymbol, aliasTypeArguments));
|
||||
return getUnionType(spreads, /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments);
|
||||
}
|
||||
const atBeginning = types.length === 0;
|
||||
const left = getSpreadType(types, symbol, aliasSymbol, aliasTypeArguments);
|
||||
if (right.flags & (TypeFlags.Null | TypeFlags.Undefined)) {
|
||||
if (right.flags & TypeFlags.Primitive || left.flags & TypeFlags.Any) {
|
||||
return left;
|
||||
}
|
||||
if (right.flags & TypeFlags.TypeParameter &&
|
||||
@@ -5795,9 +5802,18 @@ namespace ts {
|
||||
// for types like T ... T, just return ... T
|
||||
return left;
|
||||
}
|
||||
if (!(right.flags & (TypeFlags.Union | TypeFlags.Intersection | TypeFlags.TypeParameter | TypeFlags.Spread))
|
||||
&& !(left.flags & (TypeFlags.Union | TypeFlags.Intersection | TypeFlags.TypeParameter | TypeFlags.Spread))) {
|
||||
const members = createMap<Symbol | undefined>();
|
||||
if (left.flags & TypeFlags.Intersection) {
|
||||
const spreads = map((left as IntersectionType).types,
|
||||
t => getSpreadType(types.slice().concat([t, right]), symbol, aliasSymbol, aliasTypeArguments));
|
||||
return getIntersectionType(spreads, aliasSymbol, aliasTypeArguments);
|
||||
}
|
||||
if (left.flags & TypeFlags.Union) {
|
||||
const spreads = map((left as UnionType).types,
|
||||
t => getSpreadType(types.slice().concat([t, right]), symbol, aliasSymbol, aliasTypeArguments));
|
||||
return getUnionType(spreads, /*subTypeReduction*/ false, aliasSymbol, aliasTypeArguments);
|
||||
}
|
||||
if (right.flags & TypeFlags.ObjectType && left.flags & TypeFlags.ObjectType) {
|
||||
const members = createMap<Symbol>();
|
||||
const skippedPrivateMembers = createMap<boolean>();
|
||||
let stringIndexInfo = unionIndexInfos(getIndexInfoOfType(left, IndexKind.String), getIndexInfoOfType(right, IndexKind.String));
|
||||
let numberIndexInfo = unionIndexInfos(getIndexInfoOfType(left, IndexKind.Number), getIndexInfoOfType(right, IndexKind.Number));
|
||||
@@ -5820,7 +5836,6 @@ namespace ts {
|
||||
for (const leftProp of getPropertiesOfType(left)) {
|
||||
if (leftProp.flags & SymbolFlags.SetAccessor && !(leftProp.flags & SymbolFlags.GetAccessor)
|
||||
|| leftProp.name in skippedPrivateMembers) {
|
||||
// skip set-only properties (methods have already been skipped by the recursive call to getSpreadType)
|
||||
continue;
|
||||
}
|
||||
if (leftProp.name in members) {
|
||||
@@ -5836,7 +5851,7 @@ namespace ts {
|
||||
if (declarations.length) {
|
||||
result.valueDeclaration = declarations[0];
|
||||
}
|
||||
result.isReadonly = isReadonlySymbol(rightProp) || isReadonlySymbol(leftProp);
|
||||
result.isReadonly = isReadonlySymbol(leftProp) || isReadonlySymbol(rightProp);
|
||||
members[leftProp.name] = result;
|
||||
}
|
||||
}
|
||||
@@ -5846,10 +5861,9 @@ namespace ts {
|
||||
}
|
||||
return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
|
||||
}
|
||||
// one side is a type parameter (TODO: Or union or intersection)
|
||||
const spread = spreadTypes[id] = createObjectType(TypeFlags.Spread, symbol) as SpreadType;
|
||||
Debug.assert(!!(left.flags & (TypeFlags.Spread | TypeFlags.ObjectType)));
|
||||
Debug.assert(!!(right.flags & (TypeFlags.TypeParameter | TypeFlags.ObjectType)));
|
||||
Debug.assert(!!(left.flags & (TypeFlags.Spread | TypeFlags.ObjectType)), "Left flags: " + left.flags.toString(2));
|
||||
Debug.assert(!!(right.flags & (TypeFlags.TypeParameter | TypeFlags.ObjectType)), "Right flags: " + right.flags.toString(2));
|
||||
spread.left = left as SpreadType | ResolvedType;
|
||||
spread.right = right as TypeParameter | ResolvedType;
|
||||
spread.aliasSymbol = aliasSymbol;
|
||||
@@ -6802,19 +6816,19 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (source.flags & TypeFlags.Spread) {
|
||||
// you only see this for spreads with type parameters (TODO: and unions/intersections)
|
||||
if (target.flags & TypeFlags.Spread) {
|
||||
if (!(spreadTypeRelatedTo(source as SpreadType, target as SpreadType))) {
|
||||
if (source.flags & TypeFlags.Spread && target.flags & TypeFlags.Spread) {
|
||||
// you only see this for spreads with type parameters
|
||||
if (!(spreadTypeRelatedTo(source as SpreadType, target as SpreadType))) {
|
||||
if (reportErrors) {
|
||||
reportRelationError(headMessage, source, target);
|
||||
return Ternary.False;
|
||||
}
|
||||
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
|
||||
const apparentSource = getApparentType(source);
|
||||
if (result = objectTypeRelatedTo(apparentSource, source, getApparentType(target), reportStructuralErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
|
||||
const apparentSource = getApparentType(source);
|
||||
if (result = objectTypeRelatedTo(apparentSource, source, getApparentType(target), reportStructuralErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6878,40 +6892,27 @@ namespace ts {
|
||||
}
|
||||
|
||||
function spreadTypeRelatedTo(source: SpreadType, target: SpreadType): boolean {
|
||||
// (Spread ... Object) | (Spread | Object ... TypeParameter)
|
||||
// in other words, if the right side is Object, then the left side must be a Spread.
|
||||
if (source.right.flags & TypeFlags.ObjectType &&
|
||||
target.right.flags & TypeFlags.ObjectType) {
|
||||
// If the right side of a spread type is ObjectType, then the left side must be a Spread.
|
||||
// Structural compatibility of the spreads' object types are checked separately in isRelatedTo,
|
||||
// so just skip them for now.
|
||||
if (source.right.flags & TypeFlags.ObjectType || target.right.flags & TypeFlags.ObjectType) {
|
||||
return spreadTypeRelatedTo(source.right.flags & TypeFlags.ObjectType ? source.left as SpreadType : source,
|
||||
target.right.flags & TypeFlags.ObjectType ? target.left as SpreadType : target);
|
||||
}
|
||||
// If both right sides are type parameters, then they must be identical for the spread types to be related.
|
||||
// It also means that the left sides are either spread types or object types.
|
||||
|
||||
// if one left is object and the other is spread, that means the second has another type parameter. which isn't allowed
|
||||
if (target.right.symbol !== source.right.symbol) {
|
||||
return false;
|
||||
}
|
||||
if (source.left.flags & TypeFlags.Spread && target.left.flags & TypeFlags.Spread) {
|
||||
// If the left sides are both spread types, then recursively check them.
|
||||
return spreadTypeRelatedTo(source.left as SpreadType, target.left as SpreadType);
|
||||
}
|
||||
if (source.right.flags & TypeFlags.ObjectType) {
|
||||
/// target.right is TypeParameter, skip source.right, but keep looking at target
|
||||
return spreadTypeRelatedTo(source.left as SpreadType, target);
|
||||
}
|
||||
if (target.right.flags & TypeFlags.ObjectType) {
|
||||
/// source.right is TypeParameter, skip target.right, but keep looking at source
|
||||
return spreadTypeRelatedTo(source, target.left as SpreadType);
|
||||
}
|
||||
else {
|
||||
// both rights are type parameters, so they must be identical
|
||||
// and both lefts must be the same:
|
||||
// if one left is object and the other is spread, that means the second has another type parameter. which isn't allowed
|
||||
if (target.right.symbol !== source.right.symbol) {
|
||||
return false;
|
||||
}
|
||||
if (source.left.flags & TypeFlags.Spread && target.left.flags & TypeFlags.Spread) {
|
||||
return spreadTypeRelatedTo(source.left as SpreadType, target.left as SpreadType);
|
||||
}
|
||||
else if (source.left.flags & TypeFlags.ObjectType && target.left.flags & TypeFlags.ObjectType) {
|
||||
return true; // let structural compatibility figure it out later
|
||||
}
|
||||
else {
|
||||
// one side is a spread, so it must have more type parameters, which will not be matched by the other side
|
||||
// return false immediately instead of descending to find this out.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the left sides are both object types, then isRelatedTo will check the structural compatibility next.
|
||||
// Otherwise, one side has more type parameters than the other and the spread types are not related.
|
||||
return !!(source.left.flags & TypeFlags.ObjectType && target.left.flags & TypeFlags.ObjectType);
|
||||
}
|
||||
|
||||
function isIdenticalTo(source: Type, target: Type): Ternary {
|
||||
@@ -6927,8 +6928,8 @@ namespace ts {
|
||||
}
|
||||
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
|
||||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
|
||||
if (result = eachTypeRelatedToSomeType(<TypeOperatorType>source, <TypeOperatorType>target, /*reportErrors*/ false)) {
|
||||
if (result &= eachTypeRelatedToSomeType(<TypeOperatorType>target, <TypeOperatorType>source, /*reportErrors*/ false)) {
|
||||
if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target, /*reportErrors*/ false)) {
|
||||
if (result &= eachTypeRelatedToSomeType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source, /*reportErrors*/ false)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -6951,7 +6952,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
for (const t of (<TypeOperatorType>type).types) {
|
||||
for (const t of (<UnionOrIntersectionType>type).types) {
|
||||
if (isKnownProperty(t, name)) {
|
||||
return true;
|
||||
}
|
||||
@@ -6989,7 +6990,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function eachTypeRelatedToSomeType(source: TypeOperatorType, target: TypeOperatorType, reportErrors: boolean): Ternary {
|
||||
function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||
let result = Ternary.True;
|
||||
const sourceTypes = source.types;
|
||||
for (const sourceType of sourceTypes) {
|
||||
@@ -7002,7 +7003,7 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function typeRelatedToSomeType(source: Type, target: TypeOperatorType, reportErrors: boolean): Ternary {
|
||||
function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||
const targetTypes = target.types;
|
||||
if (target.flags & TypeFlags.Union && containsType(targetTypes, source)) {
|
||||
return Ternary.True;
|
||||
@@ -7017,7 +7018,7 @@ namespace ts {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
function typeRelatedToEachType(source: Type, target: TypeOperatorType, reportErrors: boolean): Ternary {
|
||||
function typeRelatedToEachType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||
let result = Ternary.True;
|
||||
const targetTypes = target.types;
|
||||
for (const targetType of targetTypes) {
|
||||
@@ -7030,7 +7031,7 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function someTypeRelatedToType(source: TypeOperatorType, target: Type, reportErrors: boolean): Ternary {
|
||||
function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
|
||||
const sourceTypes = source.types;
|
||||
if (source.flags & TypeFlags.Union && containsType(sourceTypes, target)) {
|
||||
return Ternary.True;
|
||||
@@ -7045,7 +7046,7 @@ namespace ts {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
function eachTypeRelatedToType(source: TypeOperatorType, target: Type, reportErrors: boolean): Ternary {
|
||||
function eachTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
|
||||
let result = Ternary.True;
|
||||
const sourceTypes = source.types;
|
||||
for (const sourceType of sourceTypes) {
|
||||
@@ -7990,10 +7991,10 @@ namespace ts {
|
||||
return !!(type.flags & TypeFlags.TypeParameter ||
|
||||
type.flags & TypeFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeParameters) ||
|
||||
type.flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
|
||||
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeParameters(<TypeOperatorType>type));
|
||||
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeParameters(<UnionOrIntersectionType>type));
|
||||
}
|
||||
|
||||
function couldUnionOrIntersectionContainTypeParameters(type: TypeOperatorType): boolean {
|
||||
function couldUnionOrIntersectionContainTypeParameters(type: UnionOrIntersectionType): boolean {
|
||||
if (type.couldContainTypeParameters === undefined) {
|
||||
type.couldContainTypeParameters = forEach(type.types, couldContainTypeParameters);
|
||||
}
|
||||
@@ -8001,7 +8002,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isTypeParameterAtTopLevel(type: Type, typeParameter: TypeParameter): boolean {
|
||||
return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((<TypeOperatorType>type).types, t => isTypeParameterAtTopLevel(t, typeParameter));
|
||||
return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((<UnionOrIntersectionType>type).types, t => isTypeParameterAtTopLevel(t, typeParameter));
|
||||
}
|
||||
|
||||
function inferTypes(context: InferenceContext, originalSource: Type, originalTarget: Type) {
|
||||
@@ -8031,7 +8032,7 @@ namespace ts {
|
||||
// Source and target are both unions or both intersections. If source and target
|
||||
// are the same type, just relate each constituent type to itself.
|
||||
if (source === target) {
|
||||
for (const t of (<TypeOperatorType>source).types) {
|
||||
for (const t of (<UnionOrIntersectionType>source).types) {
|
||||
inferFromTypes(t, t);
|
||||
}
|
||||
return;
|
||||
@@ -8043,14 +8044,14 @@ namespace ts {
|
||||
// and string literals because the number and string types are not represented as unions
|
||||
// of all their possible values.
|
||||
let matchingTypes: Type[];
|
||||
for (const t of (<TypeOperatorType>source).types) {
|
||||
if (typeIdenticalToSomeType(t, (<TypeOperatorType>target).types)) {
|
||||
for (const t of (<UnionOrIntersectionType>source).types) {
|
||||
if (typeIdenticalToSomeType(t, (<UnionOrIntersectionType>target).types)) {
|
||||
(matchingTypes || (matchingTypes = [])).push(t);
|
||||
inferFromTypes(t, t);
|
||||
}
|
||||
else if (t.flags & (TypeFlags.NumberLiteral | TypeFlags.StringLiteral)) {
|
||||
const b = getBaseTypeOfLiteralType(t);
|
||||
if (typeIdenticalToSomeType(b, (<TypeOperatorType>target).types)) {
|
||||
if (typeIdenticalToSomeType(b, (<UnionOrIntersectionType>target).types)) {
|
||||
(matchingTypes || (matchingTypes = [])).push(t, b);
|
||||
}
|
||||
}
|
||||
@@ -8059,8 +8060,8 @@ namespace ts {
|
||||
// removing the identically matched constituents. For example, when inferring from
|
||||
// 'string | string[]' to 'string | T' we reduce the types to 'string[]' and 'T'.
|
||||
if (matchingTypes) {
|
||||
source = removeTypesFromUnionOrIntersection(<TypeOperatorType>source, matchingTypes);
|
||||
target = removeTypesFromUnionOrIntersection(<TypeOperatorType>target, matchingTypes);
|
||||
source = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>source, matchingTypes);
|
||||
target = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>target, matchingTypes);
|
||||
}
|
||||
}
|
||||
if (target.flags & TypeFlags.TypeParameter) {
|
||||
@@ -8107,7 +8108,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (target.flags & TypeFlags.UnionOrIntersection) {
|
||||
const targetTypes = (<TypeOperatorType>target).types;
|
||||
const targetTypes = (<UnionOrIntersectionType>target).types;
|
||||
let typeParameterCount = 0;
|
||||
let typeParameter: TypeParameter;
|
||||
// First infer to each type in union or intersection that isn't a type parameter
|
||||
@@ -8131,7 +8132,7 @@ namespace ts {
|
||||
}
|
||||
else if (source.flags & TypeFlags.UnionOrIntersection) {
|
||||
// Source is a union or intersection type, infer from each constituent type
|
||||
const sourceTypes = (<TypeOperatorType>source).types;
|
||||
const sourceTypes = (<UnionOrIntersectionType>source).types;
|
||||
for (const sourceType of sourceTypes) {
|
||||
inferFromTypes(sourceType, target);
|
||||
}
|
||||
@@ -8236,7 +8237,7 @@ namespace ts {
|
||||
* Return a new union or intersection type computed by removing a given set of types
|
||||
* from a given union or intersection type.
|
||||
*/
|
||||
function removeTypesFromUnionOrIntersection(type: TypeOperatorType, typesToRemove: Type[]) {
|
||||
function removeTypesFromUnionOrIntersection(type: UnionOrIntersectionType, typesToRemove: Type[]) {
|
||||
const reducedTypes: Type[] = [];
|
||||
for (const t of type.types) {
|
||||
if (!typeIdenticalToSomeType(t, typesToRemove)) {
|
||||
@@ -8549,7 +8550,7 @@ namespace ts {
|
||||
return getTypeFacts(constraint || emptyObjectType);
|
||||
}
|
||||
if (flags & TypeFlags.UnionOrIntersection) {
|
||||
return getTypeFactsOfTypes((<TypeOperatorType>type).types);
|
||||
return getTypeFactsOfTypes((<UnionOrIntersectionType>type).types);
|
||||
}
|
||||
return TypeFacts.All;
|
||||
}
|
||||
@@ -10632,13 +10633,6 @@ namespace ts {
|
||||
type = checkExpressionForMutableLocation((<ShorthandPropertyAssignment>memberDecl).name, contextualMapper);
|
||||
}
|
||||
|
||||
if (hasProperty(propertiesTable, member.name)) {
|
||||
const existingPropType = getTypeOfSymbol(propertiesTable[member.name]);
|
||||
if (!isTypeIdenticalTo(existingPropType, type)) {
|
||||
error(memberDecl.name, Diagnostics.Cannot_change_type_of_property_0_from_1_to_2, member.name, typeToString(existingPropType), typeToString(type));
|
||||
}
|
||||
}
|
||||
|
||||
typeFlags |= type.flags;
|
||||
const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
|
||||
if (inDestructuringPattern) {
|
||||
@@ -10992,7 +10986,7 @@ namespace ts {
|
||||
elemType = checkExpression(node.tagName);
|
||||
}
|
||||
if (elemType.flags & TypeFlags.Union) {
|
||||
const types = (<TypeOperatorType>elemType).types;
|
||||
const types = (<UnionOrIntersectionType>elemType).types;
|
||||
return getUnionType(types.map(type => {
|
||||
return getResolvedJsxType(node, type, elemClassType);
|
||||
}), /*subtypeReduction*/ true);
|
||||
@@ -13557,7 +13551,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
const types = (<TypeOperatorType>type).types;
|
||||
const types = (<UnionOrIntersectionType>type).types;
|
||||
for (const t of types) {
|
||||
if (maybeTypeOfKind(t, kind)) {
|
||||
return true;
|
||||
@@ -13575,7 +13569,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
const types = (<TypeOperatorType>type).types;
|
||||
const types = (<UnionOrIntersectionType>type).types;
|
||||
for (const t of types) {
|
||||
if (!isTypeOfKind(t, kind)) {
|
||||
return false;
|
||||
@@ -13584,7 +13578,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
const types = (<TypeOperatorType>type).types;
|
||||
const types = (<UnionOrIntersectionType>type).types;
|
||||
for (const t of types) {
|
||||
if (isTypeOfKind(t, kind)) {
|
||||
return true;
|
||||
@@ -14980,9 +14974,11 @@ namespace ts {
|
||||
forEach(node.members, checkSourceElement);
|
||||
if (produceDiagnostics) {
|
||||
const type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
|
||||
checkIndexConstraints(type);
|
||||
checkTypeForDuplicateIndexSignatures(node);
|
||||
checkObjectTypeForDuplicateDeclarations(node);
|
||||
if (type.flags & TypeFlags.ObjectType) {
|
||||
checkIndexConstraints(type);
|
||||
checkTypeForDuplicateIndexSignatures(node);
|
||||
checkObjectTypeForDuplicateDeclarations(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20317,17 +20313,6 @@ namespace ts {
|
||||
|
||||
for (const prop of node.properties) {
|
||||
if (prop.kind === SyntaxKind.SpreadElementExpression) {
|
||||
const target = (prop as SpreadElementExpression).expression;
|
||||
switch (target.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
case SyntaxKind.NullKeyword:
|
||||
break;
|
||||
default:
|
||||
grammarErrorOnNode(target, Diagnostics.Spread_properties_must_be_identifiers_property_accesses_or_object_literals);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
const name = prop.name;
|
||||
|
||||
@@ -1967,17 +1967,9 @@
|
||||
"category": "Error",
|
||||
"code": 2696
|
||||
},
|
||||
"Spread properties must be identifiers, property accesses, or object literals.": {
|
||||
"category": "Error",
|
||||
"code": 2697
|
||||
},
|
||||
"Cannot change type of property '{0}' from '{1}' to '{2}'.": {
|
||||
"category": "Error",
|
||||
"code": 2698
|
||||
},
|
||||
"Interface declaration cannot contain a spread property.": {
|
||||
"category": "Error",
|
||||
"code": 2699
|
||||
"code": 2697
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
|
||||
@@ -1802,7 +1802,7 @@ namespace ts {
|
||||
|
||||
export interface JSDocRecordType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocRecordType;
|
||||
literal: TypeLiteralNode;
|
||||
literal: TypeLiteralNode;
|
||||
}
|
||||
|
||||
export interface JSDocTypeReference extends JSDocType {
|
||||
@@ -2536,7 +2536,7 @@ namespace ts {
|
||||
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
|
||||
mapper?: TypeMapper; // Type mapper for instantiation alias
|
||||
referenced?: boolean; // True if alias symbol has been referenced as a value
|
||||
referenced?: boolean; // True if alias symbol has been referenced as a value
|
||||
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
|
||||
leftSpread?: Symbol; // Left source for synthetic spread property
|
||||
rightSpread?: Symbol; // Right source for synthetic spread property
|
||||
hasNonUniformType?: boolean; // True if constituents have non-uniform types
|
||||
@@ -2755,7 +2755,7 @@ namespace ts {
|
||||
instantiations: Map<TypeReference>; // Generic instantiation cache
|
||||
}
|
||||
|
||||
|
||||
export interface UnionOrIntersectionType extends Type {
|
||||
types: Type[]; // Constituent types
|
||||
/* @internal */
|
||||
resolvedProperties: SymbolTable; // Cache of resolved properties
|
||||
@@ -2763,9 +2763,9 @@ namespace ts {
|
||||
couldContainTypeParameters: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface UnionType extends UnionOrIntersectionType { }
|
||||
|
||||
|
||||
export interface IntersectionType extends UnionOrIntersectionType { }
|
||||
|
||||
/* @internal */
|
||||
export interface SpreadType extends Type {
|
||||
@@ -2782,7 +2782,7 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
// Resolved object, spread, union, or intersection type
|
||||
// Resolved object, spread, union, or intersection type
|
||||
export interface ResolvedType extends ObjectType, UnionOrIntersectionType {
|
||||
members: SymbolTable; // Properties by name
|
||||
properties: Symbol[]; // Properties
|
||||
callSignatures: Signature[]; // Call signatures of type
|
||||
|
||||
@@ -458,7 +458,7 @@ namespace ts.FindAllReferences {
|
||||
return [localParentType.symbol];
|
||||
}
|
||||
else if (localParentType.flags & TypeFlags.UnionOrIntersection) {
|
||||
return getSymbolsForClassAndInterfaceComponents(<TypeOperatorType>localParentType);
|
||||
return getSymbolsForClassAndInterfaceComponents(<UnionOrIntersectionType>localParentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -630,13 +630,13 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
}
|
||||
|
||||
function getSymbolsForClassAndInterfaceComponents(type: TypeOperatorType, result: Symbol[] = []): Symbol[] {
|
||||
function getSymbolsForClassAndInterfaceComponents(type: UnionOrIntersectionType, result: Symbol[] = []): Symbol[] {
|
||||
for (const componentType of type.types) {
|
||||
if (componentType.symbol && componentType.symbol.getFlags() & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
result.push(componentType.symbol);
|
||||
}
|
||||
if (componentType.getFlags() & TypeFlags.UnionOrIntersection) {
|
||||
getSymbolsForClassAndInterfaceComponents(<TypeOperatorType>componentType, result);
|
||||
getSymbolsForClassAndInterfaceComponents(<UnionOrIntersectionType>componentType, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user