|
|
|
@@ -67,6 +67,7 @@ namespace ts {
|
|
|
|
|
let enumCount = 0;
|
|
|
|
|
let instantiationDepth = 0;
|
|
|
|
|
let constraintDepth = 0;
|
|
|
|
|
let currentNode: Node | undefined;
|
|
|
|
|
|
|
|
|
|
const emptySymbols = createSymbolTable();
|
|
|
|
|
const identityMapper: (type: Type) => Type = identity;
|
|
|
|
@@ -3592,14 +3593,15 @@ namespace ts {
|
|
|
|
|
|
|
|
|
|
function typeReferenceToTypeNode(type: TypeReference) {
|
|
|
|
|
const typeArguments: ReadonlyArray<Type> = type.typeArguments || emptyArray;
|
|
|
|
|
if (type.target === globalArrayType) {
|
|
|
|
|
if (type.target === globalArrayType || type.target === globalReadonlyArrayType) {
|
|
|
|
|
if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) {
|
|
|
|
|
const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context);
|
|
|
|
|
return createTypeReferenceNode("Array", [typeArgumentNode]);
|
|
|
|
|
return createTypeReferenceNode(type.target === globalArrayType ? "Array" : "ReadonlyArray", [typeArgumentNode]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const elementType = typeToTypeNodeHelper(typeArguments[0], context);
|
|
|
|
|
return createArrayTypeNode(elementType);
|
|
|
|
|
const arrayType = createArrayTypeNode(elementType);
|
|
|
|
|
return type.target === globalArrayType ? arrayType : createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, arrayType);
|
|
|
|
|
}
|
|
|
|
|
else if (type.target.objectFlags & ObjectFlags.Tuple) {
|
|
|
|
|
if (typeArguments.length > 0) {
|
|
|
|
@@ -3612,11 +3614,13 @@ namespace ts {
|
|
|
|
|
createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) :
|
|
|
|
|
createOptionalTypeNode(tupleConstituentNodes[i]);
|
|
|
|
|
}
|
|
|
|
|
return createTupleTypeNode(tupleConstituentNodes);
|
|
|
|
|
const tupleTypeNode = createTupleTypeNode(tupleConstituentNodes);
|
|
|
|
|
return (<TupleType>type.target).readonly ? createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (context.encounteredError || (context.flags & NodeBuilderFlags.AllowEmptyTuple)) {
|
|
|
|
|
return createTupleTypeNode([]);
|
|
|
|
|
const tupleTypeNode = createTupleTypeNode([]);
|
|
|
|
|
return (<TupleType>type.target).readonly ? createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode;
|
|
|
|
|
}
|
|
|
|
|
context.encounteredError = true;
|
|
|
|
|
return undefined!; // TODO: GH#18217
|
|
|
|
@@ -5280,17 +5284,18 @@ namespace ts {
|
|
|
|
|
let objectFlags = ObjectFlags.ObjectLiteral;
|
|
|
|
|
forEach(pattern.elements, e => {
|
|
|
|
|
const name = e.propertyName || <Identifier>e.name;
|
|
|
|
|
if (isComputedNonLiteralName(name)) {
|
|
|
|
|
// do not include computed properties in the implied type
|
|
|
|
|
objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (e.dotDotDotToken) {
|
|
|
|
|
stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const text = getTextOfPropertyName(name);
|
|
|
|
|
const exprType = getLiteralTypeFromPropertyName(name);
|
|
|
|
|
if (!isTypeUsableAsPropertyName(exprType)) {
|
|
|
|
|
// do not include computed properties in the implied type
|
|
|
|
|
objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const text = getPropertyNameFromType(exprType);
|
|
|
|
|
const flags = SymbolFlags.Property | (e.initializer ? SymbolFlags.Optional : 0);
|
|
|
|
|
const symbol = createSymbol(flags, text);
|
|
|
|
|
symbol.type = getTypeFromBindingElement(e, includePatternInType, reportErrors);
|
|
|
|
@@ -5931,7 +5936,7 @@ namespace ts {
|
|
|
|
|
function getBaseTypes(type: InterfaceType): BaseType[] {
|
|
|
|
|
if (!type.resolvedBaseTypes) {
|
|
|
|
|
if (type.objectFlags & ObjectFlags.Tuple) {
|
|
|
|
|
type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters || emptyArray))];
|
|
|
|
|
type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters || emptyArray), (<TupleType>type).readonly)];
|
|
|
|
|
}
|
|
|
|
|
else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
|
|
|
|
if (type.symbol.flags & SymbolFlags.Class) {
|
|
|
|
@@ -6399,9 +6404,9 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Indicates whether a type can be used as a late-bound name.
|
|
|
|
|
* Indicates whether a type can be used as a property name.
|
|
|
|
|
*/
|
|
|
|
|
function isTypeUsableAsLateBoundName(type: Type): type is LiteralType | UniqueESSymbolType {
|
|
|
|
|
function isTypeUsableAsPropertyName(type: Type): type is StringLiteralType | NumberLiteralType | UniqueESSymbolType {
|
|
|
|
|
return !!(type.flags & TypeFlags.StringOrNumberLiteralOrUnique);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -6416,7 +6421,7 @@ namespace ts {
|
|
|
|
|
function isLateBindableName(node: DeclarationName): node is LateBoundName {
|
|
|
|
|
return isComputedPropertyName(node)
|
|
|
|
|
&& isEntityNameExpression(node.expression)
|
|
|
|
|
&& isTypeUsableAsLateBoundName(checkComputedPropertyName(node));
|
|
|
|
|
&& isTypeUsableAsPropertyName(checkComputedPropertyName(node));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isLateBoundName(name: __String): boolean {
|
|
|
|
@@ -6448,11 +6453,11 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets the symbolic name for a late-bound member from its type.
|
|
|
|
|
* Gets the symbolic name for a member from its type.
|
|
|
|
|
*/
|
|
|
|
|
function getLateBoundNameFromType(type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String {
|
|
|
|
|
function getPropertyNameFromType(type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String {
|
|
|
|
|
if (type.flags & TypeFlags.UniqueESSymbol) {
|
|
|
|
|
return `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String;
|
|
|
|
|
return (<UniqueESSymbolType>type).escapedName;
|
|
|
|
|
}
|
|
|
|
|
if (type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
|
|
|
|
|
return escapeLeadingUnderscores("" + (<StringLiteralType | NumberLiteralType>type).value);
|
|
|
|
@@ -6518,8 +6523,8 @@ namespace ts {
|
|
|
|
|
// fall back to the early-bound name of this member.
|
|
|
|
|
links.resolvedSymbol = decl.symbol;
|
|
|
|
|
const type = checkComputedPropertyName(decl.name);
|
|
|
|
|
if (isTypeUsableAsLateBoundName(type)) {
|
|
|
|
|
const memberName = getLateBoundNameFromType(type);
|
|
|
|
|
if (isTypeUsableAsPropertyName(type)) {
|
|
|
|
|
const memberName = getPropertyNameFromType(type);
|
|
|
|
|
const symbolFlags = decl.symbol.flags;
|
|
|
|
|
|
|
|
|
|
// Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations.
|
|
|
|
@@ -7168,8 +7173,8 @@ namespace ts {
|
|
|
|
|
const propType = instantiateType(templateType, templateMapper);
|
|
|
|
|
// If the current iteration type constituent is a string literal type, create a property.
|
|
|
|
|
// Otherwise, for type string create a string index signature.
|
|
|
|
|
if (t.flags & TypeFlags.StringOrNumberLiteralOrUnique) {
|
|
|
|
|
const propName = getLateBoundNameFromType(t as LiteralType);
|
|
|
|
|
if (isTypeUsableAsPropertyName(t)) {
|
|
|
|
|
const propName = getPropertyNameFromType(t);
|
|
|
|
|
const modifiersProp = getPropertyOfType(modifiersType, propName);
|
|
|
|
|
const isOptional = !!(templateModifiers & MappedTypeModifiers.IncludeOptional ||
|
|
|
|
|
!(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional);
|
|
|
|
@@ -7354,7 +7359,8 @@ namespace ts {
|
|
|
|
|
function isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes): boolean {
|
|
|
|
|
const list = obj.properties as NodeArray<ObjectLiteralElementLike | JsxAttributeLike>;
|
|
|
|
|
return list.some(property => {
|
|
|
|
|
const name = property.name && getTextOfPropertyName(property.name);
|
|
|
|
|
const nameType = property.name && getLiteralTypeFromPropertyName(property.name);
|
|
|
|
|
const name = nameType && isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined;
|
|
|
|
|
const expected = name === undefined ? undefined : getTypeOfPropertyOfType(contextualType, name);
|
|
|
|
|
return !!expected && isLiteralType(expected) && !isTypeIdenticalTo(getTypeOfNode(property), expected);
|
|
|
|
|
});
|
|
|
|
@@ -7520,6 +7526,7 @@ namespace ts {
|
|
|
|
|
// very high likelyhood we're dealing with an infinite generic type that perpetually generates
|
|
|
|
|
// new type identities as we descend into it. We stop the recursion here and mark this type
|
|
|
|
|
// and the outer types as having circular constraints.
|
|
|
|
|
error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
|
|
|
|
|
nonTerminating = true;
|
|
|
|
|
return t.immediateBaseConstraint = noConstraintType;
|
|
|
|
|
}
|
|
|
|
@@ -7638,7 +7645,7 @@ namespace ts {
|
|
|
|
|
const typeVariable = getHomomorphicTypeVariable(type);
|
|
|
|
|
if (typeVariable) {
|
|
|
|
|
const constraint = getConstraintOfTypeParameter(typeVariable);
|
|
|
|
|
if (constraint && (isArrayType(constraint) || isReadonlyArrayType(constraint) || isTupleType(constraint))) {
|
|
|
|
|
if (constraint && (isArrayType(constraint) || isTupleType(constraint))) {
|
|
|
|
|
const mapper = makeUnaryTypeMapper(typeVariable, constraint);
|
|
|
|
|
return instantiateType(type, combineTypeMappers(mapper, type.mapper));
|
|
|
|
|
}
|
|
|
|
@@ -9035,22 +9042,22 @@ namespace ts {
|
|
|
|
|
return createTypeFromGenericGlobalType(getGlobalIterableIteratorType(/*reportErrors*/ true), [iteratedType]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createArrayType(elementType: Type): ObjectType {
|
|
|
|
|
return createTypeFromGenericGlobalType(globalArrayType, [elementType]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createReadonlyArrayType(elementType: Type): ObjectType {
|
|
|
|
|
return createTypeFromGenericGlobalType(globalReadonlyArrayType, [elementType]);
|
|
|
|
|
function createArrayType(elementType: Type, readonly?: boolean): ObjectType {
|
|
|
|
|
return createTypeFromGenericGlobalType(readonly ? globalReadonlyArrayType : globalArrayType, [elementType]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getTypeFromArrayTypeNode(node: ArrayTypeNode): Type {
|
|
|
|
|
const links = getNodeLinks(node);
|
|
|
|
|
if (!links.resolvedType) {
|
|
|
|
|
links.resolvedType = createArrayType(getTypeFromTypeNode(node.elementType));
|
|
|
|
|
links.resolvedType = createArrayType(getTypeFromTypeNode(node.elementType), isReadonlyTypeOperator(node.parent));
|
|
|
|
|
}
|
|
|
|
|
return links.resolvedType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isReadonlyTypeOperator(node: Node) {
|
|
|
|
|
return isTypeOperatorNode(node) && node.operator === SyntaxKind.ReadonlyKeyword;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We represent tuple types as type references to synthesized generic interface types created by
|
|
|
|
|
// this function. The types are of the form:
|
|
|
|
|
//
|
|
|
|
@@ -9058,7 +9065,7 @@ namespace ts {
|
|
|
|
|
//
|
|
|
|
|
// Note that the generic type created by this function has no symbol associated with it. The same
|
|
|
|
|
// is true for each of the synthesized type parameters.
|
|
|
|
|
function createTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, associatedNames: __String[] | undefined): TupleType {
|
|
|
|
|
function createTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, associatedNames: __String[] | undefined): TupleType {
|
|
|
|
|
let typeParameters: TypeParameter[] | undefined;
|
|
|
|
|
const properties: Symbol[] = [];
|
|
|
|
|
const maxLength = hasRestElement ? arity - 1 : arity;
|
|
|
|
@@ -9067,7 +9074,8 @@ namespace ts {
|
|
|
|
|
for (let i = 0; i < arity; i++) {
|
|
|
|
|
const typeParameter = typeParameters[i] = createTypeParameter();
|
|
|
|
|
if (i < maxLength) {
|
|
|
|
|
const property = createSymbol(SymbolFlags.Property | (i >= minLength ? SymbolFlags.Optional : 0), "" + i as __String);
|
|
|
|
|
const property = createSymbol(SymbolFlags.Property | (i >= minLength ? SymbolFlags.Optional : 0),
|
|
|
|
|
"" + i as __String, readonly ? CheckFlags.Readonly : 0);
|
|
|
|
|
property.type = typeParameter;
|
|
|
|
|
properties.push(property);
|
|
|
|
|
}
|
|
|
|
@@ -9096,25 +9104,26 @@ namespace ts {
|
|
|
|
|
type.declaredNumberIndexInfo = undefined;
|
|
|
|
|
type.minLength = minLength;
|
|
|
|
|
type.hasRestElement = hasRestElement;
|
|
|
|
|
type.readonly = readonly;
|
|
|
|
|
type.associatedNames = associatedNames;
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, associatedNames?: __String[]): GenericType {
|
|
|
|
|
const key = arity + (hasRestElement ? "+" : ",") + minLength + (associatedNames && associatedNames.length ? "," + associatedNames.join(",") : "");
|
|
|
|
|
function getTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, associatedNames?: __String[]): GenericType {
|
|
|
|
|
const key = arity + (hasRestElement ? "+" : ",") + minLength + (readonly ? "R" : "") + (associatedNames && associatedNames.length ? "," + associatedNames.join(",") : "");
|
|
|
|
|
let type = tupleTypes.get(key);
|
|
|
|
|
if (!type) {
|
|
|
|
|
tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, associatedNames));
|
|
|
|
|
tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, associatedNames));
|
|
|
|
|
}
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createTupleType(elementTypes: ReadonlyArray<Type>, minLength = elementTypes.length, hasRestElement = false, associatedNames?: __String[]) {
|
|
|
|
|
function createTupleType(elementTypes: ReadonlyArray<Type>, minLength = elementTypes.length, hasRestElement = false, readonly = false, associatedNames?: __String[]) {
|
|
|
|
|
const arity = elementTypes.length;
|
|
|
|
|
if (arity === 1 && hasRestElement) {
|
|
|
|
|
return createArrayType(elementTypes[0]);
|
|
|
|
|
}
|
|
|
|
|
const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, associatedNames);
|
|
|
|
|
const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, associatedNames);
|
|
|
|
|
return elementTypes.length ? createTypeReference(tupleType, elementTypes) : tupleType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -9128,7 +9137,7 @@ namespace ts {
|
|
|
|
|
const type = getTypeFromTypeNode(n);
|
|
|
|
|
return n === restElement && getIndexTypeOfType(type, IndexKind.Number) || type;
|
|
|
|
|
});
|
|
|
|
|
links.resolvedType = createTupleType(elementTypes, minLength, !!restElement);
|
|
|
|
|
links.resolvedType = createTupleType(elementTypes, minLength, !!restElement, isReadonlyTypeOperator(node.parent));
|
|
|
|
|
}
|
|
|
|
|
return links.resolvedType;
|
|
|
|
|
}
|
|
|
|
@@ -9143,6 +9152,7 @@ namespace ts {
|
|
|
|
|
(type.typeArguments || emptyArray).slice(index),
|
|
|
|
|
Math.max(0, tuple.minLength - index),
|
|
|
|
|
tuple.hasRestElement,
|
|
|
|
|
tuple.readonly,
|
|
|
|
|
tuple.associatedNames && tuple.associatedNames.slice(index),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
@@ -9232,18 +9242,6 @@ namespace ts {
|
|
|
|
|
return includes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isSubtypeOfAny(source: Type, targets: ReadonlyArray<Type>): boolean {
|
|
|
|
|
for (const target of targets) {
|
|
|
|
|
if (source !== target && isTypeSubtypeOf(source, target) && (
|
|
|
|
|
!(getObjectFlags(getTargetType(source)) & ObjectFlags.Class) ||
|
|
|
|
|
!(getObjectFlags(getTargetType(target)) & ObjectFlags.Class) ||
|
|
|
|
|
isTypeDerivedFrom(source, target))) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isSetOfLiteralsFromSameEnum(types: ReadonlyArray<Type>): boolean {
|
|
|
|
|
const first = types[0];
|
|
|
|
|
if (first.flags & TypeFlags.EnumLiteral) {
|
|
|
|
@@ -9260,17 +9258,42 @@ namespace ts {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function removeSubtypes(types: Type[]) {
|
|
|
|
|
if (types.length === 0 || isSetOfLiteralsFromSameEnum(types)) {
|
|
|
|
|
return;
|
|
|
|
|
function removeSubtypes(types: Type[], primitivesOnly: boolean): boolean {
|
|
|
|
|
const len = types.length;
|
|
|
|
|
if (len === 0 || isSetOfLiteralsFromSameEnum(types)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
let i = types.length;
|
|
|
|
|
let i = len;
|
|
|
|
|
let count = 0;
|
|
|
|
|
while (i > 0) {
|
|
|
|
|
i--;
|
|
|
|
|
if (isSubtypeOfAny(types[i], types)) {
|
|
|
|
|
orderedRemoveItemAt(types, i);
|
|
|
|
|
const source = types[i];
|
|
|
|
|
for (const target of types) {
|
|
|
|
|
if (source !== target) {
|
|
|
|
|
if (count === 10000) {
|
|
|
|
|
// After 10000 subtype checks we estimate the remaining amount of work by assuming the
|
|
|
|
|
// same ratio of checks to removals. If the estimated number of remaining type checks is
|
|
|
|
|
// greater than an upper limit we deem the union type too complex to represent. The
|
|
|
|
|
// upper limit is 25M for unions of primitives only, and 1M otherwise. This for example
|
|
|
|
|
// caps union types at 5000 unique literal types and 1000 unique object types.
|
|
|
|
|
const estimatedCount = (count / (len - i)) * len;
|
|
|
|
|
if (estimatedCount > (primitivesOnly ? 25000000 : 1000000)) {
|
|
|
|
|
error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
count++;
|
|
|
|
|
if (isTypeSubtypeOf(source, target) && (
|
|
|
|
|
!(getObjectFlags(getTargetType(source)) & ObjectFlags.Class) ||
|
|
|
|
|
!(getObjectFlags(getTargetType(target)) & ObjectFlags.Class) ||
|
|
|
|
|
isTypeDerivedFrom(source, target))) {
|
|
|
|
|
orderedRemoveItemAt(types, i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function removeRedundantLiteralTypes(types: Type[], includes: TypeFlags) {
|
|
|
|
@@ -9317,7 +9340,9 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case UnionReduction.Subtype:
|
|
|
|
|
removeSubtypes(typeSet);
|
|
|
|
|
if (!removeSubtypes(typeSet, !(includes & TypeFlags.StructuredOrInstantiable))) {
|
|
|
|
|
return errorType;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (typeSet.length === 0) {
|
|
|
|
@@ -9680,6 +9705,9 @@ namespace ts {
|
|
|
|
|
? getESSymbolLikeTypeForNode(walkUpParenthesizedTypes(node.parent))
|
|
|
|
|
: errorType;
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxKind.ReadonlyKeyword:
|
|
|
|
|
links.resolvedType = getTypeFromTypeNode(node.type);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return links.resolvedType!; // TODO: GH#18217
|
|
|
|
@@ -9722,8 +9750,8 @@ namespace ts {
|
|
|
|
|
|
|
|
|
|
function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, cacheSymbol: boolean, missingType: Type) {
|
|
|
|
|
const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
|
|
|
|
|
const propName = isTypeUsableAsLateBoundName(indexType) ?
|
|
|
|
|
getLateBoundNameFromType(indexType) :
|
|
|
|
|
const propName = isTypeUsableAsPropertyName(indexType) ?
|
|
|
|
|
getPropertyNameFromType(indexType) :
|
|
|
|
|
accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ?
|
|
|
|
|
getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>accessExpression.argumentExpression).name)) :
|
|
|
|
|
accessNode && isPropertyName(accessNode) ?
|
|
|
|
@@ -10413,6 +10441,7 @@ namespace ts {
|
|
|
|
|
function createUniqueESSymbolType(symbol: Symbol) {
|
|
|
|
|
const type = <UniqueESSymbolType>createType(TypeFlags.UniqueESSymbol);
|
|
|
|
|
type.symbol = symbol;
|
|
|
|
|
type.escapedName = `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String;
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -10633,7 +10662,11 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getRestrictiveTypeParameter(tp: TypeParameter) {
|
|
|
|
|
return !tp.constraint ? tp : tp.restrictiveInstantiation || (tp.restrictiveInstantiation = createTypeParameter(tp.symbol));
|
|
|
|
|
return tp.constraint === unknownType ? tp : tp.restrictiveInstantiation || (
|
|
|
|
|
tp.restrictiveInstantiation = createTypeParameter(tp.symbol),
|
|
|
|
|
(tp.restrictiveInstantiation as TypeParameter).constraint = unknownType,
|
|
|
|
|
tp.restrictiveInstantiation
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function restrictiveMapper(type: Type) {
|
|
|
|
@@ -10707,7 +10740,7 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
// Keep the flags from the symbol we're instantiating. Mark that is instantiated, and
|
|
|
|
|
// also transient so that we can just store data on it directly.
|
|
|
|
|
const result = createSymbol(symbol.flags, symbol.escapedName, CheckFlags.Instantiated | getCheckFlags(symbol) & (CheckFlags.Late | CheckFlags.OptionalParameter | CheckFlags.RestParameter));
|
|
|
|
|
const result = createSymbol(symbol.flags, symbol.escapedName, CheckFlags.Instantiated | getCheckFlags(symbol) & (CheckFlags.Readonly | CheckFlags.Late | CheckFlags.OptionalParameter | CheckFlags.RestParameter));
|
|
|
|
|
result.declarations = symbol.declarations;
|
|
|
|
|
result.parent = symbol.parent;
|
|
|
|
|
result.target = symbol;
|
|
|
|
@@ -10838,11 +10871,11 @@ namespace ts {
|
|
|
|
|
return errorType;
|
|
|
|
|
}
|
|
|
|
|
type.instantiating = true;
|
|
|
|
|
const modifiers = getMappedTypeModifiers(type);
|
|
|
|
|
const result = mapType(mappedTypeVariable, t => {
|
|
|
|
|
if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType) {
|
|
|
|
|
const replacementMapper = createReplacementMapper(typeVariable, t, mapper);
|
|
|
|
|
return isArrayType(t) ? createArrayType(instantiateMappedTypeTemplate(type, numberType, /*isOptional*/ true, replacementMapper)) :
|
|
|
|
|
isReadonlyArrayType(t) ? createReadonlyArrayType(instantiateMappedTypeTemplate(type, numberType, /*isOptional*/ true, replacementMapper)) :
|
|
|
|
|
return isArrayType(t) ? createArrayType(instantiateMappedTypeTemplate(type, numberType, /*isOptional*/ true, replacementMapper), getModifiedReadonlyState(isReadonlyArrayType(t), modifiers)) :
|
|
|
|
|
isTupleType(t) ? instantiateMappedTupleType(t, type, replacementMapper) :
|
|
|
|
|
instantiateAnonymousType(type, replacementMapper);
|
|
|
|
|
}
|
|
|
|
@@ -10855,6 +10888,10 @@ namespace ts {
|
|
|
|
|
return instantiateAnonymousType(type, mapper);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getModifiedReadonlyState(state: boolean, modifiers: MappedTypeModifiers) {
|
|
|
|
|
return modifiers & MappedTypeModifiers.IncludeReadonly ? true : modifiers & MappedTypeModifiers.ExcludeReadonly ? false : state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function instantiateMappedTupleType(tupleType: TupleTypeReference, mappedType: MappedType, mapper: TypeMapper) {
|
|
|
|
|
const minLength = tupleType.target.minLength;
|
|
|
|
|
const elementTypes = map(tupleType.typeArguments || emptyArray, (_, i) =>
|
|
|
|
@@ -10863,7 +10900,8 @@ namespace ts {
|
|
|
|
|
const newMinLength = modifiers & MappedTypeModifiers.IncludeOptional ? 0 :
|
|
|
|
|
modifiers & MappedTypeModifiers.ExcludeOptional ? getTypeReferenceArity(tupleType) - (tupleType.target.hasRestElement ? 1 : 0) :
|
|
|
|
|
minLength;
|
|
|
|
|
return createTupleType(elementTypes, newMinLength, tupleType.target.hasRestElement, tupleType.target.associatedNames);
|
|
|
|
|
const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, modifiers);
|
|
|
|
|
return createTupleType(elementTypes, newMinLength, tupleType.target.hasRestElement, newReadonly, tupleType.target.associatedNames);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) {
|
|
|
|
@@ -10936,6 +10974,7 @@ namespace ts {
|
|
|
|
|
// We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing
|
|
|
|
|
// with a combination of infinite generic types that perpetually generate new type identities. We stop
|
|
|
|
|
// the recursion here by yielding the error type.
|
|
|
|
|
error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
|
|
|
|
|
return errorType;
|
|
|
|
|
}
|
|
|
|
|
instantiationDepth++;
|
|
|
|
@@ -11300,7 +11339,7 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
if (resultObj.error) {
|
|
|
|
|
const reportedDiag = resultObj.error;
|
|
|
|
|
const propertyName = isTypeUsableAsLateBoundName(nameType) ? getLateBoundNameFromType(nameType) : undefined;
|
|
|
|
|
const propertyName = isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined;
|
|
|
|
|
const targetProp = propertyName !== undefined ? getPropertyOfType(target, propertyName) : undefined;
|
|
|
|
|
|
|
|
|
|
let issuedElaboration = false;
|
|
|
|
@@ -12725,7 +12764,7 @@ namespace ts {
|
|
|
|
|
errorInfo = saveErrorInfo;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (isTupleType(source) && (isArrayType(target) || isReadonlyArrayType(target)) || isArrayType(source) && isReadonlyArrayType(target)) {
|
|
|
|
|
else if (isReadonlyArrayType(target) ? isArrayType(source) || isTupleType(source) : isArrayType(target) && isTupleType(source) && !source.target.readonly) {
|
|
|
|
|
return isRelatedTo(getIndexTypeOfType(source, IndexKind.Number) || anyType, getIndexTypeOfType(target, IndexKind.Number) || anyType, reportErrors);
|
|
|
|
|
}
|
|
|
|
|
// Even if relationship doesn't hold for unions, intersections, or generic type references,
|
|
|
|
@@ -13266,11 +13305,8 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getVariances(type: GenericType): Variance[] {
|
|
|
|
|
if (!strictFunctionTypes) {
|
|
|
|
|
return emptyArray;
|
|
|
|
|
}
|
|
|
|
|
if (type === globalArrayType || type === globalReadonlyArrayType) {
|
|
|
|
|
// Arrays are known to be covariant, no need to spend time computing this (emptyArray implies covariance for all parameters)
|
|
|
|
|
// Arrays and tuples are known to be covariant, no need to spend time computing this (emptyArray implies covariance for all parameters)
|
|
|
|
|
if (!strictFunctionTypes || type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple) {
|
|
|
|
|
return emptyArray;
|
|
|
|
|
}
|
|
|
|
|
return getVariancesWorker(type.typeParameters, type, getMarkerTypeReference);
|
|
|
|
@@ -13560,7 +13596,7 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isArrayType(type: Type): boolean {
|
|
|
|
|
return !!(getObjectFlags(type) & ObjectFlags.Reference) && (<TypeReference>type).target === globalArrayType;
|
|
|
|
|
return !!(getObjectFlags(type) & ObjectFlags.Reference) && ((<TypeReference>type).target === globalArrayType || (<TypeReference>type).target === globalReadonlyArrayType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isReadonlyArrayType(type: Type): boolean {
|
|
|
|
@@ -13574,8 +13610,7 @@ namespace ts {
|
|
|
|
|
function isArrayLikeType(type: Type): boolean {
|
|
|
|
|
// A type is array-like if it is a reference to the global Array or global ReadonlyArray type,
|
|
|
|
|
// or if it is not the undefined or null type and if it is assignable to ReadonlyArray<any>
|
|
|
|
|
return getObjectFlags(type) & ObjectFlags.Reference && ((<TypeReference>type).target === globalArrayType || (<TypeReference>type).target === globalReadonlyArrayType) ||
|
|
|
|
|
!(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
|
|
|
|
|
return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isEmptyArrayLiteralType(type: Type): boolean {
|
|
|
|
@@ -14184,16 +14219,13 @@ namespace ts {
|
|
|
|
|
// For arrays and tuples we infer new arrays and tuples where the reverse mapping has been
|
|
|
|
|
// applied to the element type(s).
|
|
|
|
|
if (isArrayType(source)) {
|
|
|
|
|
return createArrayType(inferReverseMappedType((<TypeReference>source).typeArguments![0], target, constraint));
|
|
|
|
|
}
|
|
|
|
|
if (isReadonlyArrayType(source)) {
|
|
|
|
|
return createReadonlyArrayType(inferReverseMappedType((<TypeReference>source).typeArguments![0], target, constraint));
|
|
|
|
|
return createArrayType(inferReverseMappedType((<TypeReference>source).typeArguments![0], target, constraint), isReadonlyArrayType(source));
|
|
|
|
|
}
|
|
|
|
|
if (isTupleType(source)) {
|
|
|
|
|
const elementTypes = map(source.typeArguments || emptyArray, t => inferReverseMappedType(t, target, constraint));
|
|
|
|
|
const minLength = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ?
|
|
|
|
|
getTypeReferenceArity(source) - (source.target.hasRestElement ? 1 : 0) : source.target.minLength;
|
|
|
|
|
return createTupleType(elementTypes, minLength, source.target.hasRestElement, source.target.associatedNames);
|
|
|
|
|
return createTupleType(elementTypes, minLength, source.target.hasRestElement, source.target.readonly, source.target.associatedNames);
|
|
|
|
|
}
|
|
|
|
|
// For all other object types we infer a new object type where the reverse mapping has been
|
|
|
|
|
// applied to the type of each property.
|
|
|
|
@@ -14567,7 +14599,12 @@ namespace ts {
|
|
|
|
|
priority |= InferencePriority.MappedTypeConstraint;
|
|
|
|
|
inferFromTypes(getIndexType(source), constraintType);
|
|
|
|
|
priority = savePriority;
|
|
|
|
|
inferFromTypes(getUnionType(map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(<MappedType>target));
|
|
|
|
|
const valueTypes = compact([
|
|
|
|
|
getIndexTypeOfType(source, IndexKind.String),
|
|
|
|
|
getIndexTypeOfType(source, IndexKind.Number),
|
|
|
|
|
...map(getPropertiesOfType(source), getTypeOfSymbol)
|
|
|
|
|
]);
|
|
|
|
|
inferFromTypes(getUnionType(valueTypes), getTemplateTypeFromMappedType(<MappedType>target));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
@@ -15172,7 +15209,9 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getTypeOfDestructuredProperty(type: Type, name: PropertyName) {
|
|
|
|
|
const text = getTextOfPropertyName(name);
|
|
|
|
|
const nameType = getLiteralTypeFromPropertyName(name);
|
|
|
|
|
if (!isTypeUsableAsPropertyName(nameType)) return errorType;
|
|
|
|
|
const text = getPropertyNameFromType(nameType);
|
|
|
|
|
return getConstraintForLocation(getTypeOfPropertyOfType(type, text), name) ||
|
|
|
|
|
isNumericLiteralName(text) && getIndexTypeOfType(type, IndexKind.Number) ||
|
|
|
|
|
getIndexTypeOfType(type, IndexKind.String) ||
|
|
|
|
@@ -16018,6 +16057,15 @@ namespace ts {
|
|
|
|
|
assumeTrue = !assumeTrue;
|
|
|
|
|
}
|
|
|
|
|
const valueType = getTypeOfExpression(value);
|
|
|
|
|
if ((type.flags & TypeFlags.Unknown) && (operator === SyntaxKind.EqualsEqualsEqualsToken) && assumeTrue) {
|
|
|
|
|
if (valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive)) {
|
|
|
|
|
return valueType;
|
|
|
|
|
}
|
|
|
|
|
if (valueType.flags & TypeFlags.Object) {
|
|
|
|
|
return nonPrimitiveType;
|
|
|
|
|
}
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
if (valueType.flags & TypeFlags.Nullable) {
|
|
|
|
|
if (!strictNullChecks) {
|
|
|
|
|
return type;
|
|
|
|
@@ -17304,9 +17352,10 @@ namespace ts {
|
|
|
|
|
const parentDeclaration = declaration.parent.parent;
|
|
|
|
|
const name = declaration.propertyName || declaration.name;
|
|
|
|
|
const parentType = getContextualTypeForVariableLikeDeclaration(parentDeclaration);
|
|
|
|
|
if (parentType && !isBindingPattern(name)) {
|
|
|
|
|
const text = getTextOfPropertyName(name);
|
|
|
|
|
if (text !== undefined) {
|
|
|
|
|
if (parentType && !isBindingPattern(name) && !isComputedNonLiteralName(name)) {
|
|
|
|
|
const nameType = getLiteralTypeFromPropertyName(name);
|
|
|
|
|
if (isTypeUsableAsPropertyName(nameType)) {
|
|
|
|
|
const text = getPropertyNameFromType(nameType);
|
|
|
|
|
return getTypeOfPropertyOfType(parentType, text);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -18092,7 +18141,9 @@ namespace ts {
|
|
|
|
|
return createTupleType(elementTypes, minLength, hasRestElement);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return getArrayLiteralType(elementTypes, UnionReduction.Subtype);
|
|
|
|
|
return createArrayType(elementTypes.length ?
|
|
|
|
|
getUnionType(elementTypes, UnionReduction.Subtype) :
|
|
|
|
|
strictNullChecks ? implicitNeverType : undefinedWideningType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getArrayLiteralTupleTypeIfApplicable(elementTypes: Type[], contextualType: Type | undefined, hasRestElement: boolean, elementCount = elementTypes.length) {
|
|
|
|
@@ -18121,12 +18172,6 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getArrayLiteralType(elementTypes: Type[], unionReduction = UnionReduction.Literal) {
|
|
|
|
|
return createArrayType(elementTypes.length ?
|
|
|
|
|
getUnionType(elementTypes, unionReduction) :
|
|
|
|
|
strictNullChecks ? implicitNeverType : undefinedWideningType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isNumericName(name: DeclarationName): boolean {
|
|
|
|
|
switch (name.kind) {
|
|
|
|
|
case SyntaxKind.ComputedPropertyName:
|
|
|
|
@@ -18263,10 +18308,9 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
typeFlags |= type.flags;
|
|
|
|
|
const nameType = computedNameType && computedNameType.flags & TypeFlags.StringOrNumberLiteralOrUnique ?
|
|
|
|
|
<LiteralType | UniqueESSymbolType>computedNameType : undefined;
|
|
|
|
|
const nameType = computedNameType && isTypeUsableAsPropertyName(computedNameType) ? computedNameType : undefined;
|
|
|
|
|
const prop = nameType ?
|
|
|
|
|
createSymbol(SymbolFlags.Property | member.flags, getLateBoundNameFromType(nameType), CheckFlags.Late) :
|
|
|
|
|
createSymbol(SymbolFlags.Property | member.flags, getPropertyNameFromType(nameType), CheckFlags.Late) :
|
|
|
|
|
createSymbol(SymbolFlags.Property | member.flags, member.escapedName);
|
|
|
|
|
if (nameType) {
|
|
|
|
|
prop.nameType = nameType;
|
|
|
|
@@ -21409,7 +21453,7 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
const minArgumentCount = getMinArgumentCount(source);
|
|
|
|
|
const minLength = minArgumentCount < start ? 0 : minArgumentCount - start;
|
|
|
|
|
return createTupleType(types, minLength, !!restType, names);
|
|
|
|
|
return createTupleType(types, minLength, !!restType, /*readonly*/ false, names);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getParameterCount(signature: Signature) {
|
|
|
|
@@ -22315,15 +22359,15 @@ namespace ts {
|
|
|
|
|
function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: NodeArray<ObjectLiteralElementLike>, rightIsThis = false) {
|
|
|
|
|
if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
|
|
|
|
const name = property.name;
|
|
|
|
|
const text = getTextOfPropertyName(name);
|
|
|
|
|
if (text) {
|
|
|
|
|
const exprType = getLiteralTypeFromPropertyName(name);
|
|
|
|
|
if (isTypeUsableAsPropertyName(exprType)) {
|
|
|
|
|
const text = getPropertyNameFromType(exprType);
|
|
|
|
|
const prop = getPropertyOfType(objectLiteralType, text);
|
|
|
|
|
if (prop) {
|
|
|
|
|
markPropertyAsReferenced(prop, property, rightIsThis);
|
|
|
|
|
checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const exprType = getLiteralTypeFromPropertyName(name);
|
|
|
|
|
const elementType = getIndexedAccessType(objectLiteralType, exprType, name);
|
|
|
|
|
const type = getFlowTypeOfDestructuring(property, elementType);
|
|
|
|
|
return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type);
|
|
|
|
@@ -23046,7 +23090,7 @@ namespace ts {
|
|
|
|
|
return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration, type: Type, checkMode?: CheckMode) {
|
|
|
|
|
function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration | QualifiedName, type: Type, checkMode?: CheckMode) {
|
|
|
|
|
if (checkMode === CheckMode.Inferential) {
|
|
|
|
|
const signature = getSingleCallSignature(type);
|
|
|
|
|
if (signature && signature.typeParameters) {
|
|
|
|
@@ -23116,15 +23160,10 @@ namespace ts {
|
|
|
|
|
// have the wildcard function type; this form of type check is used during overload resolution to exclude
|
|
|
|
|
// contextually typed function and arrow expressions in the initial phase.
|
|
|
|
|
function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): Type {
|
|
|
|
|
let type: Type;
|
|
|
|
|
if (node.kind === SyntaxKind.QualifiedName) {
|
|
|
|
|
type = checkQualifiedName(<QualifiedName>node);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
const uninstantiatedType = checkExpressionWorker(node, checkMode, forceTuple);
|
|
|
|
|
type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const saveCurrentNode = currentNode;
|
|
|
|
|
currentNode = node;
|
|
|
|
|
const uninstantiatedType = checkExpressionWorker(node, checkMode, forceTuple);
|
|
|
|
|
const type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
|
|
|
|
|
if (isConstEnumObjectType(type)) {
|
|
|
|
|
// enum object type for const enums are only permitted in:
|
|
|
|
|
// - 'left' in property access
|
|
|
|
@@ -23140,6 +23179,7 @@ namespace ts {
|
|
|
|
|
error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
currentNode = saveCurrentNode;
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -23151,7 +23191,7 @@ namespace ts {
|
|
|
|
|
return checkExpression(node.expression, checkMode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkExpressionWorker(node: Expression, checkMode: CheckMode | undefined, forceTuple?: boolean): Type {
|
|
|
|
|
function checkExpressionWorker(node: Expression | QualifiedName, checkMode: CheckMode | undefined, forceTuple?: boolean): Type {
|
|
|
|
|
switch (node.kind) {
|
|
|
|
|
case SyntaxKind.Identifier:
|
|
|
|
|
return checkIdentifier(<Identifier>node);
|
|
|
|
@@ -23184,6 +23224,8 @@ namespace ts {
|
|
|
|
|
return checkObjectLiteral(<ObjectLiteralExpression>node, checkMode);
|
|
|
|
|
case SyntaxKind.PropertyAccessExpression:
|
|
|
|
|
return checkPropertyAccessExpression(<PropertyAccessExpression>node);
|
|
|
|
|
case SyntaxKind.QualifiedName:
|
|
|
|
|
return checkQualifiedName(<QualifiedName>node);
|
|
|
|
|
case SyntaxKind.ElementAccessExpression:
|
|
|
|
|
return checkIndexedAccess(<ElementAccessExpression>node);
|
|
|
|
|
case SyntaxKind.CallExpression:
|
|
|
|
@@ -23307,7 +23349,7 @@ namespace ts {
|
|
|
|
|
|
|
|
|
|
// Only check rest parameter type if it's not a binding pattern. Since binding patterns are
|
|
|
|
|
// not allowed in a rest parameter, we already have an error from checkGrammarParameterList.
|
|
|
|
|
if (node.dotDotDotToken && !isBindingPattern(node.name) && !isTypeAssignableTo(getTypeOfSymbol(node.symbol), anyArrayType)) {
|
|
|
|
|
if (node.dotDotDotToken && !isBindingPattern(node.name) && !isTypeAssignableTo(getTypeOfSymbol(node.symbol), anyReadonlyArrayType)) {
|
|
|
|
|
error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -25638,13 +25680,14 @@ namespace ts {
|
|
|
|
|
const parent = node.parent.parent;
|
|
|
|
|
const parentType = getTypeForBindingElementParent(parent);
|
|
|
|
|
const name = node.propertyName || node.name;
|
|
|
|
|
if (!isBindingPattern(name)) {
|
|
|
|
|
const nameText = getTextOfPropertyName(name);
|
|
|
|
|
if (nameText) {
|
|
|
|
|
const property = getPropertyOfType(parentType!, nameText); // TODO: GH#18217
|
|
|
|
|
if (!isBindingPattern(name) && parentType) {
|
|
|
|
|
const exprType = getLiteralTypeFromPropertyName(name);
|
|
|
|
|
if (isTypeUsableAsPropertyName(exprType)) {
|
|
|
|
|
const nameText = getPropertyNameFromType(exprType);
|
|
|
|
|
const property = getPropertyOfType(parentType, nameText);
|
|
|
|
|
if (property) {
|
|
|
|
|
markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference.
|
|
|
|
|
checkPropertyAccessibility(parent, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, parentType!, property);
|
|
|
|
|
checkPropertyAccessibility(parent, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, parentType, property);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -27864,10 +27907,15 @@ namespace ts {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkSourceElement(node: Node | undefined): void {
|
|
|
|
|
if (!node) {
|
|
|
|
|
return;
|
|
|
|
|
if (node) {
|
|
|
|
|
const saveCurrentNode = currentNode;
|
|
|
|
|
currentNode = node;
|
|
|
|
|
checkSourceElementWorker(node);
|
|
|
|
|
currentNode = saveCurrentNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkSourceElementWorker(node: Node): void {
|
|
|
|
|
if (isInJSFile(node)) {
|
|
|
|
|
forEach((node as JSDocContainer).jsDoc, ({ tags }) => forEach(tags, checkSourceElement));
|
|
|
|
|
}
|
|
|
|
@@ -28125,32 +28173,36 @@ namespace ts {
|
|
|
|
|
|
|
|
|
|
function checkDeferredNodes(context: SourceFile) {
|
|
|
|
|
const links = getNodeLinks(context);
|
|
|
|
|
if (!links.deferredNodes) {
|
|
|
|
|
return;
|
|
|
|
|
if (links.deferredNodes) {
|
|
|
|
|
links.deferredNodes.forEach(checkDeferredNode);
|
|
|
|
|
}
|
|
|
|
|
links.deferredNodes.forEach(node => {
|
|
|
|
|
switch (node.kind) {
|
|
|
|
|
case SyntaxKind.FunctionExpression:
|
|
|
|
|
case SyntaxKind.ArrowFunction:
|
|
|
|
|
case SyntaxKind.MethodDeclaration:
|
|
|
|
|
case SyntaxKind.MethodSignature:
|
|
|
|
|
checkFunctionExpressionOrObjectLiteralMethodDeferred(<FunctionExpression>node);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxKind.GetAccessor:
|
|
|
|
|
case SyntaxKind.SetAccessor:
|
|
|
|
|
checkAccessorDeclaration(<AccessorDeclaration>node);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxKind.ClassExpression:
|
|
|
|
|
checkClassExpressionDeferred(<ClassExpression>node);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxKind.JsxSelfClosingElement:
|
|
|
|
|
checkJsxSelfClosingElementDeferred(<JsxSelfClosingElement>node);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxKind.JsxElement:
|
|
|
|
|
checkJsxElementDeferred(<JsxElement>node);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkDeferredNode(node: Node) {
|
|
|
|
|
const saveCurrentNode = currentNode;
|
|
|
|
|
currentNode = node;
|
|
|
|
|
switch (node.kind) {
|
|
|
|
|
case SyntaxKind.FunctionExpression:
|
|
|
|
|
case SyntaxKind.ArrowFunction:
|
|
|
|
|
case SyntaxKind.MethodDeclaration:
|
|
|
|
|
case SyntaxKind.MethodSignature:
|
|
|
|
|
checkFunctionExpressionOrObjectLiteralMethodDeferred(<FunctionExpression>node);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxKind.GetAccessor:
|
|
|
|
|
case SyntaxKind.SetAccessor:
|
|
|
|
|
checkAccessorDeclaration(<AccessorDeclaration>node);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxKind.ClassExpression:
|
|
|
|
|
checkClassExpressionDeferred(<ClassExpression>node);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxKind.JsxSelfClosingElement:
|
|
|
|
|
checkJsxSelfClosingElementDeferred(<JsxSelfClosingElement>node);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxKind.JsxElement:
|
|
|
|
|
checkJsxElementDeferred(<JsxElement>node);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
currentNode = saveCurrentNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkSourceFile(node: SourceFile) {
|
|
|
|
@@ -30653,6 +30705,11 @@ namespace ts {
|
|
|
|
|
return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_not_allowed_here);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (node.operator === SyntaxKind.ReadonlyKeyword) {
|
|
|
|
|
if (node.type.kind !== SyntaxKind.ArrayType && node.type.kind !== SyntaxKind.TupleType) {
|
|
|
|
|
return grammarErrorOnFirstToken(node, Diagnostics.readonly_type_modifier_is_only_permitted_on_array_and_tuple_types, tokenToString(SyntaxKind.SymbolKeyword));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkGrammarForInvalidDynamicName(node: DeclarationName, message: DiagnosticMessage) {
|
|
|
|
|