@@ -4919,7 +4919,7 @@ namespace ts {
4919
4919
if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkDeclarationInitializer(declaration)) & TypeFlags.Undefined)) {
4920
4920
type = getTypeWithFacts(type, TypeFacts.NEUndefined);
4921
4921
}
4922
- return declaration.initializer && !getContextualTypeForVariableLikeDeclaration (walkUpBindingElementsAndPatterns(declaration)) ?
4922
+ return declaration.initializer && !getEffectiveTypeAnnotationNode (walkUpBindingElementsAndPatterns(declaration)) ?
4923
4923
getUnionType([type, checkDeclarationInitializer(declaration)], UnionReduction.Subtype) :
4924
4924
type;
4925
4925
}
@@ -6930,7 +6930,7 @@ namespace ts {
6930
6930
function resolveUnionTypeMembers(type: UnionType) {
6931
6931
// The members and properties collections are empty for union types. To get all properties of a union
6932
6932
// type use getPropertiesOfType (only the language service uses this).
6933
- const callSignatures = getUnionSignatures(map(type.types, t => getSignaturesOfType(t, SignatureKind.Call)));
6933
+ const callSignatures = getUnionSignatures(map(type.types, t => t === globalFunctionType ? [unknownSignature] : getSignaturesOfType(t, SignatureKind.Call)));
6934
6934
const constructSignatures = getUnionSignatures(map(type.types, t => getSignaturesOfType(t, SignatureKind.Construct)));
6935
6935
const stringIndexInfo = getUnionIndexInfo(type.types, IndexKind.String);
6936
6936
const numberIndexInfo = getUnionIndexInfo(type.types, IndexKind.Number);
@@ -7084,6 +7084,39 @@ namespace ts {
7084
7084
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
7085
7085
}
7086
7086
7087
+ // Return the lower bound of the key type in a mapped type. Intuitively, the lower
7088
+ // bound includes those keys that are known to always be present, for example because
7089
+ // because of constraints on type parameters (e.g. 'keyof T' for a constrained T).
7090
+ function getLowerBoundOfKeyType(type: Type): Type {
7091
+ if (type.flags & (TypeFlags.Any | TypeFlags.Primitive)) {
7092
+ return type;
7093
+ }
7094
+ if (type.flags & TypeFlags.Index) {
7095
+ return getIndexType(getApparentType((<IndexType>type).type));
7096
+ }
7097
+ if (type.flags & TypeFlags.Conditional) {
7098
+ return getLowerBoundOfConditionalType(<ConditionalType>type);
7099
+ }
7100
+ if (type.flags & TypeFlags.Union) {
7101
+ return getUnionType(sameMap((<UnionType>type).types, getLowerBoundOfKeyType));
7102
+ }
7103
+ if (type.flags & TypeFlags.Intersection) {
7104
+ return getIntersectionType(sameMap((<UnionType>type).types, getLowerBoundOfKeyType));
7105
+ }
7106
+ return neverType;
7107
+ }
7108
+
7109
+ function getLowerBoundOfConditionalType(type: ConditionalType) {
7110
+ if (type.root.isDistributive) {
7111
+ const constraint = getLowerBoundOfKeyType(type.checkType);
7112
+ if (constraint !== type.checkType) {
7113
+ const mapper = makeUnaryTypeMapper(type.root.checkType, constraint);
7114
+ return getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper));
7115
+ }
7116
+ }
7117
+ return type;
7118
+ }
7119
+
7087
7120
/** Resolve the members of a mapped type { [P in K]: T } */
7088
7121
function resolveMappedTypeMembers(type: MappedType) {
7089
7122
const members: SymbolTable = createSymbolTable();
@@ -7112,10 +7145,7 @@ namespace ts {
7112
7145
}
7113
7146
}
7114
7147
else {
7115
- // If the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X.
7116
- // Then iterate over the constituents of the key type.
7117
- const iterationType = constraintType.flags & TypeFlags.Index ? getIndexType(getApparentType((<IndexType>constraintType).type)) : constraintType;
7118
- forEachType(iterationType, addMemberForKeyType);
7148
+ forEachType(getLowerBoundOfKeyType(constraintType), addMemberForKeyType);
7119
7149
}
7120
7150
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
7121
7151
@@ -7669,38 +7699,37 @@ namespace ts {
7669
7699
return props[0];
7670
7700
}
7671
7701
let declarations: Declaration[] | undefined;
7672
- let commonType : Type | undefined;
7702
+ let firstType : Type | undefined;
7673
7703
let nameType: Type | undefined;
7674
7704
const propTypes: Type[] = [];
7675
- let first = true;
7676
- let commonValueDeclaration: Declaration | undefined;
7705
+ let firstValueDeclaration: Declaration | undefined;
7677
7706
let hasNonUniformValueDeclaration = false;
7678
7707
for (const prop of props) {
7679
- if (!commonValueDeclaration ) {
7680
- commonValueDeclaration = prop.valueDeclaration;
7708
+ if (!firstValueDeclaration ) {
7709
+ firstValueDeclaration = prop.valueDeclaration;
7681
7710
}
7682
- else if (prop.valueDeclaration !== commonValueDeclaration ) {
7711
+ else if (prop.valueDeclaration !== firstValueDeclaration ) {
7683
7712
hasNonUniformValueDeclaration = true;
7684
7713
}
7685
7714
declarations = addRange(declarations, prop.declarations);
7686
7715
const type = getTypeOfSymbol(prop);
7687
- if (first ) {
7688
- commonType = type;
7716
+ if (!firstType ) {
7717
+ firstType = type;
7689
7718
nameType = prop.nameType;
7690
- first = false;
7691
7719
}
7692
- else {
7693
- if (type !== commonType) {
7694
- checkFlags |= CheckFlags.HasNonUniformType;
7695
- }
7720
+ else if (type !== firstType) {
7721
+ checkFlags |= CheckFlags.HasNonUniformType;
7722
+ }
7723
+ if (isLiteralType(type)) {
7724
+ checkFlags |= CheckFlags.HasLiteralType;
7696
7725
}
7697
7726
propTypes.push(type);
7698
7727
}
7699
7728
addRange(propTypes, indexTypes);
7700
7729
const result = createSymbol(SymbolFlags.Property | commonFlags, name, syntheticFlag | checkFlags);
7701
7730
result.containingType = containingType;
7702
- if (!hasNonUniformValueDeclaration && commonValueDeclaration ) {
7703
- result.valueDeclaration = commonValueDeclaration ;
7731
+ if (!hasNonUniformValueDeclaration && firstValueDeclaration ) {
7732
+ result.valueDeclaration = firstValueDeclaration ;
7704
7733
}
7705
7734
result.declarations = declarations!;
7706
7735
result.nameType = nameType;
@@ -7928,22 +7957,17 @@ namespace ts {
7928
7957
const numTypeArguments = length(typeArguments);
7929
7958
if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) {
7930
7959
const result = typeArguments ? typeArguments.slice() : [];
7931
-
7932
- // Map an unsatisfied type parameter with a default type.
7933
- // If a type parameter does not have a default type, or if the default type
7934
- // is a forward reference, the empty object type is used.
7935
- const baseDefaultType = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
7936
- const circularityMapper = createTypeMapper(typeParameters!, map(typeParameters!, () => baseDefaultType));
7960
+ // Map invalid forward references in default types to the error type
7937
7961
for (let i = numTypeArguments; i < numTypeParameters; i++) {
7938
- result[i] = instantiateType(getConstraintFromTypeParameter(typeParameters![i]) || baseDefaultType, circularityMapper) ;
7962
+ result[i] = errorType ;
7939
7963
}
7964
+ const baseDefaultType = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
7940
7965
for (let i = numTypeArguments; i < numTypeParameters; i++) {
7941
- const mapper = createTypeMapper(typeParameters!, result);
7942
7966
let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
7943
7967
if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) {
7944
7968
defaultType = anyType;
7945
7969
}
7946
- result[i] = defaultType ? instantiateType(defaultType, mapper ) : baseDefaultType;
7970
+ result[i] = defaultType ? instantiateType(defaultType, createTypeMapper(typeParameters!, result) ) : baseDefaultType;
7947
7971
}
7948
7972
result.length = typeParameters!.length;
7949
7973
return result;
@@ -11016,8 +11040,7 @@ namespace ts {
11016
11040
11017
11041
function hasContextSensitiveReturnExpression(node: FunctionLikeDeclaration) {
11018
11042
// TODO(anhans): A block should be context-sensitive if it has a context-sensitive return value.
11019
- const body = node.body!;
11020
- return body.kind === SyntaxKind.Block ? false : isContextSensitive(body);
11043
+ return !!node.body && node.body.kind !== SyntaxKind.Block && isContextSensitive(node.body);
11021
11044
}
11022
11045
11023
11046
function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration {
@@ -14814,25 +14837,18 @@ namespace ts {
14814
14837
}
14815
14838
14816
14839
function isDiscriminantType(type: Type): boolean {
14817
- if (type.flags & TypeFlags.Union) {
14818
- if (type.flags & (TypeFlags.Boolean | TypeFlags.EnumLiteral)) {
14819
- return true;
14820
- }
14821
- let combined = 0;
14822
- for (const t of (<UnionType>type).types) combined |= t.flags;
14823
- if (combined & TypeFlags.Unit && !(combined & TypeFlags.Instantiable)) {
14824
- return true;
14825
- }
14826
- }
14827
- return false;
14840
+ return !!(type.flags & TypeFlags.Union &&
14841
+ (type.flags & (TypeFlags.Boolean | TypeFlags.EnumLiteral) || !isGenericIndexType(type)));
14828
14842
}
14829
14843
14830
14844
function isDiscriminantProperty(type: Type | undefined, name: __String) {
14831
14845
if (type && type.flags & TypeFlags.Union) {
14832
14846
const prop = getUnionOrIntersectionProperty(<UnionType>type, name);
14833
14847
if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) {
14834
14848
if ((<TransientSymbol>prop).isDiscriminantProperty === undefined) {
14835
- (<TransientSymbol>prop).isDiscriminantProperty = !!((<TransientSymbol>prop).checkFlags & CheckFlags.HasNonUniformType) && isDiscriminantType(getTypeOfSymbol(prop));
14849
+ (<TransientSymbol>prop).isDiscriminantProperty =
14850
+ ((<TransientSymbol>prop).checkFlags & CheckFlags.Discriminant) === CheckFlags.Discriminant &&
14851
+ isDiscriminantType(getTypeOfSymbol(prop));
14836
14852
}
14837
14853
return !!(<TransientSymbol>prop).isDiscriminantProperty;
14838
14854
}
@@ -19263,8 +19279,8 @@ namespace ts {
19263
19279
}
19264
19280
}
19265
19281
19266
- function isValidPropertyAccessForCompletions(node: PropertyAccessExpression | ImportTypeNode, type: Type, property: Symbol): boolean {
19267
- return isValidPropertyAccessWithType(node, node.kind !== SyntaxKind.ImportType && node.expression.kind === SyntaxKind.SuperKeyword, property.escapedName, type)
19282
+ function isValidPropertyAccessForCompletions(node: PropertyAccessExpression | ImportTypeNode | QualifiedName , type: Type, property: Symbol): boolean {
19283
+ return isValidPropertyAccessWithType(node, node.kind === SyntaxKind.PropertyAccessExpression && node.expression.kind === SyntaxKind.SuperKeyword, property.escapedName, type)
19268
19284
&& (!(property.flags & SymbolFlags.Method) || isValidMethodAccess(property, type));
19269
19285
}
19270
19286
function isValidMethodAccess(method: Symbol, actualThisType: Type): boolean {
@@ -20490,9 +20506,9 @@ namespace ts {
20490
20506
* If FuncExpr is of type Any, or of an object type that has no call or construct signatures
20491
20507
* but is a subtype of the Function interface, the call is an untyped function call.
20492
20508
*/
20493
- function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number) {
20509
+ function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number): boolean {
20494
20510
// We exclude union types because we may have a union of function types that happen to have no common signatures.
20495
- return isTypeAny(funcType) || isTypeAny(apparentFuncType) && funcType.flags & TypeFlags.TypeParameter ||
20511
+ return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!( funcType.flags & TypeFlags.TypeParameter) ||
20496
20512
!numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (TypeFlags.Union | TypeFlags.Never)) && isTypeAssignableTo(funcType, globalFunctionType);
20497
20513
}
20498
20514
@@ -22810,7 +22826,8 @@ namespace ts {
22810
22826
const type = getTypeOfExpression(initializer, /*cache*/ true);
22811
22827
const widened = getCombinedNodeFlags(declaration) & NodeFlags.Const ||
22812
22828
isDeclarationReadonly(declaration) ||
22813
- isTypeAssertion(initializer) ? type : getWidenedLiteralType(type);
22829
+ isTypeAssertion(initializer) ||
22830
+ isLiteralOfContextualType(type, getContextualType(initializer)) ? type : getWidenedLiteralType(type);
22814
22831
if (isInJSFile(declaration)) {
22815
22832
if (widened.flags & TypeFlags.Nullable) {
22816
22833
reportImplicitAny(declaration, anyType);
@@ -26465,6 +26482,7 @@ namespace ts {
26465
26482
if (produceDiagnostics) {
26466
26483
if (node.default) {
26467
26484
seenDefault = true;
26485
+ checkTypeParametersNotReferenced(node.default, typeParameterDeclarations, i);
26468
26486
}
26469
26487
else if (seenDefault) {
26470
26488
error(node, Diagnostics.Required_type_parameters_may_not_follow_optional_type_parameters);
@@ -26479,6 +26497,24 @@ namespace ts {
26479
26497
}
26480
26498
}
26481
26499
26500
+ /** Check that type parameter defaults only reference previously declared type parameters */
26501
+ function checkTypeParametersNotReferenced(root: TypeNode, typeParameters: ReadonlyArray<TypeParameterDeclaration>, index: number) {
26502
+ visit(root);
26503
+ function visit(node: Node) {
26504
+ if (node.kind === SyntaxKind.TypeReference) {
26505
+ const type = getTypeFromTypeReference(<TypeReferenceNode>node);
26506
+ if (type.flags & TypeFlags.TypeParameter) {
26507
+ for (let i = index; i < typeParameters.length; i++) {
26508
+ if (type.symbol === getSymbolOfNode(typeParameters[i])) {
26509
+ error(node, Diagnostics.Type_parameter_defaults_can_only_reference_previously_declared_type_parameters);
26510
+ }
26511
+ }
26512
+ }
26513
+ }
26514
+ forEachChild(node, visit);
26515
+ }
26516
+ }
26517
+
26482
26518
/** Check that type parameter lists are identical across multiple declarations */
26483
26519
function checkTypeParameterListsIdentical(symbol: Symbol) {
26484
26520
if (symbol.declarations.length === 1) {
0 commit comments