Skip to content

Commit 16450a0

Browse files
authored
Change the default type parameter constraints and defaults to unknown from {} (#30637)
* Change the default type parameter constraint and default to unknown from {} * Relax unknown checking outside of strictNullChecks a bit * Increase strictness on index signatures with type `unknown` so inference doesnt change surprisingly * Remove redundant switch
1 parent 8c51115 commit 16450a0

File tree

133 files changed

+1309
-835
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+1309
-835
lines changed

src/compiler/checker.ts

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7330,7 +7330,7 @@ namespace ts {
73307330
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
73317331
const constraint = getConstraintTypeFromMappedType(declaredType);
73327332
const extendedConstraint = constraint && constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
7333-
type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
7333+
type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : unknownType;
73347334
}
73357335
}
73367336
return type.modifiersType;
@@ -7773,7 +7773,7 @@ namespace ts {
77737773
* type itself. Note that the apparent type of a union type is the union type itself.
77747774
*/
77757775
function getApparentType(type: Type): Type {
7776-
const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || emptyObjectType : type;
7776+
const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || unknownType : type;
77777777
return getObjectFlags(t) & ObjectFlags.Mapped ? getApparentTypeOfMappedType(<MappedType>t) :
77787778
t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(<IntersectionType>t) :
77797779
t.flags & TypeFlags.StringLike ? globalStringType :
@@ -7783,6 +7783,7 @@ namespace ts {
77837783
t.flags & TypeFlags.ESSymbolLike ? getGlobalESSymbolType(/*reportErrors*/ languageVersion >= ScriptTarget.ES2015) :
77847784
t.flags & TypeFlags.NonPrimitive ? emptyObjectType :
77857785
t.flags & TypeFlags.Index ? keyofConstraintType :
7786+
t.flags & TypeFlags.Unknown && !strictNullChecks ? emptyObjectType :
77867787
t;
77877788
}
77887789

@@ -8106,7 +8107,7 @@ namespace ts {
81068107
const baseDefaultType = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
81078108
for (let i = numTypeArguments; i < numTypeParameters; i++) {
81088109
let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
8109-
if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) {
8110+
if (isJavaScriptImplicitAny && defaultType && (isTypeIdenticalTo(defaultType, unknownType) || isTypeIdenticalTo(defaultType, emptyObjectType))) {
81108111
defaultType = anyType;
81118112
}
81128113
result[i] = defaultType ? instantiateType(defaultType, createTypeMapper(typeParameters!, result)) : baseDefaultType;
@@ -8485,7 +8486,7 @@ namespace ts {
84858486
const typeParameters = signature.typeParameters;
84868487
if (typeParameters) {
84878488
const typeEraser = createTypeEraser(typeParameters);
8488-
const baseConstraints = map(typeParameters, tp => instantiateType(getBaseConstraintOfType(tp), typeEraser) || emptyObjectType);
8489+
const baseConstraints = map(typeParameters, tp => instantiateType(getBaseConstraintOfType(tp), typeEraser) || unknownType);
84898490
return instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true);
84908491
}
84918492
return signature;
@@ -10799,7 +10800,7 @@ namespace ts {
1079910800
* This is used during inference when instantiating type parameter defaults.
1080010801
*/
1080110802
function createBackreferenceMapper(context: InferenceContext, index: number): TypeMapper {
10802-
return t => findIndex(context.inferences, info => info.typeParameter === t) >= index ? emptyObjectType : t;
10803+
return t => findIndex(context.inferences, info => info.typeParameter === t) >= index ? unknownType : t;
1080310804
}
1080410805

1080510806
function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper;
@@ -11346,7 +11347,7 @@ namespace ts {
1134611347
function isTypeDerivedFrom(source: Type, target: Type): boolean {
1134711348
return source.flags & TypeFlags.Union ? every((<UnionType>source).types, t => isTypeDerivedFrom(t, target)) :
1134811349
target.flags & TypeFlags.Union ? some((<UnionType>target).types, t => isTypeDerivedFrom(source, t)) :
11349-
source.flags & TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || emptyObjectType, target) :
11350+
source.flags & TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || unknownType, target) :
1135011351
target === globalObjectType ? !!(source.flags & (TypeFlags.Object | TypeFlags.NonPrimitive)) :
1135111352
target === globalFunctionType ? !!(source.flags & TypeFlags.Object) && isFunctionObjectType(source as ObjectType) :
1135211353
hasBaseType(source, getTargetType(target));
@@ -13349,7 +13350,7 @@ namespace ts {
1334913350
return indexTypesIdenticalTo(source, target, kind);
1335013351
}
1335113352
const targetInfo = getIndexInfoOfType(target, kind);
13352-
if (!targetInfo || targetInfo.type.flags & TypeFlags.AnyOrUnknown && !sourceIsPrimitive) {
13353+
if (!targetInfo || targetInfo.type.flags & TypeFlags.Any && !sourceIsPrimitive) {
1335313354
// Index signature of type any permits assignment from everything but primitives
1335413355
return Ternary.True;
1335513356
}
@@ -14500,7 +14501,7 @@ namespace ts {
1450014501
const templateType = getTemplateTypeFromMappedType(target);
1450114502
const inference = createInferenceInfo(typeParameter);
1450214503
inferTypes([inference], sourceType, templateType);
14503-
return getTypeFromInference(inference) || emptyObjectType;
14504+
return getTypeFromInference(inference) || unknownType;
1450414505
}
1450514506

1450614507
function* getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean) {
@@ -15099,7 +15100,7 @@ namespace ts {
1509915100
}
1510015101

1510115102
function getDefaultTypeArgumentType(isInJavaScriptFile: boolean): Type {
15102-
return isInJavaScriptFile ? anyType : emptyObjectType;
15103+
return isInJavaScriptFile ? anyType : unknownType;
1510315104
}
1510415105

1510515106
function getInferredTypes(context: InferenceContext): Type[] {
@@ -15443,7 +15444,7 @@ namespace ts {
1544315444
return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
1544415445
}
1544515446
if (flags & TypeFlags.Instantiable) {
15446-
return getTypeFacts(getBaseConstraintOfType(type) || emptyObjectType);
15447+
return getTypeFacts(getBaseConstraintOfType(type) || unknownType);
1544715448
}
1544815449
if (flags & TypeFlags.UnionOrIntersection) {
1544915450
return getTypeFactsOfTypes((<UnionOrIntersectionType>type).types);
@@ -16754,7 +16755,7 @@ namespace ts {
1675416755
}
1675516756

1675616757
function typeHasNullableConstraint(type: Type) {
16757-
return type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || emptyObjectType, TypeFlags.Nullable);
16758+
return type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.Nullable);
1675816759
}
1675916760

1676016761
function getConstraintForLocation(type: Type, node: Node): Type;
@@ -18204,7 +18205,7 @@ namespace ts {
1820418205
}
1820518206

1820618207
function getJsxPropsTypeFromCallSignature(sig: Signature, context: JsxOpeningLikeElement) {
18207-
let propsType = getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType);
18208+
let propsType = getTypeOfFirstParameterOfSignatureWithFallback(sig, unknownType);
1820818209
propsType = getJsxManagedAttributesFromLocatedAttributes(context, getJsxNamespaceAt(context), propsType);
1820918210
const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes, context);
1821018211
if (intrinsicAttribs !== errorType) {
@@ -18278,7 +18279,7 @@ namespace ts {
1827818279
const forcedLookupLocation = getJsxElementPropertiesName(ns);
1827918280
let attributesType = forcedLookupLocation === undefined
1828018281
// If there is no type ElementAttributesProperty, return the type of the first parameter of the signature, which should be the props type
18281-
? getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType)
18282+
? getTypeOfFirstParameterOfSignatureWithFallback(sig, unknownType)
1828218283
: forcedLookupLocation === ""
1828318284
// If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead
1828418285
? getReturnTypeOfSignature(sig)
@@ -18290,7 +18291,7 @@ namespace ts {
1829018291
if (!!forcedLookupLocation && !!length(context.attributes.properties)) {
1829118292
error(context, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(forcedLookupLocation));
1829218293
}
18293-
return emptyObjectType;
18294+
return unknownType;
1829418295
}
1829518296

1829618297
attributesType = getJsxManagedAttributesFromLocatedAttributes(context, ns, attributesType);
@@ -19501,7 +19502,7 @@ namespace ts {
1950119502
undefinedDiagnostic?: DiagnosticMessage,
1950219503
nullOrUndefinedDiagnostic?: DiagnosticMessage
1950319504
): Type {
19504-
if (type.flags & TypeFlags.Unknown) {
19505+
if (strictNullChecks && type.flags & TypeFlags.Unknown) {
1950519506
error(node, Diagnostics.Object_is_of_type_unknown);
1950619507
return errorType;
1950719508
}
@@ -22000,7 +22001,7 @@ namespace ts {
2200022001
const decl = parameter.valueDeclaration as ParameterDeclaration;
2200122002
if (decl.name.kind !== SyntaxKind.Identifier) {
2200222003
// if inference didn't come up with anything but {}, fall back to the binding pattern if present.
22003-
if (links.type === emptyObjectType) {
22004+
if (links.type === unknownType) {
2200422005
links.type = getTypeFromBindingPattern(decl.name);
2200522006
}
2200622007
assignBindingElementTypes(decl.name);
@@ -22013,28 +22014,28 @@ namespace ts {
2201322014
const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
2201422015
if (globalPromiseType !== emptyGenericType) {
2201522016
// if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
22016-
promisedType = getAwaitedType(promisedType) || emptyObjectType;
22017+
promisedType = getAwaitedType(promisedType) || unknownType;
2201722018
return createTypeReference(globalPromiseType, [promisedType]);
2201822019
}
2201922020

22020-
return emptyObjectType;
22021+
return unknownType;
2202122022
}
2202222023

2202322024
function createPromiseLikeType(promisedType: Type): Type {
2202422025
// creates a `PromiseLike<T>` type where `T` is the promisedType argument
2202522026
const globalPromiseLikeType = getGlobalPromiseLikeType(/*reportErrors*/ true);
2202622027
if (globalPromiseLikeType !== emptyGenericType) {
2202722028
// if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
22028-
promisedType = getAwaitedType(promisedType) || emptyObjectType;
22029+
promisedType = getAwaitedType(promisedType) || unknownType;
2202922030
return createTypeReference(globalPromiseLikeType, [promisedType]);
2203022031
}
2203122032

22032-
return emptyObjectType;
22033+
return unknownType;
2203322034
}
2203422035

2203522036
function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall, promisedType: Type) {
2203622037
const promiseType = createPromiseType(promisedType);
22037-
if (promiseType === emptyObjectType) {
22038+
if (promiseType === unknownType) {
2203822039
error(func, isImportCall(func) ?
2203922040
Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option :
2204022041
Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option);
@@ -23467,7 +23468,7 @@ namespace ts {
2346723468
// If the contextual type is a type variable constrained to a primitive type, consider
2346823469
// this a literal context for literals of that primitive type. For example, given a
2346923470
// type parameter 'T extends string', infer string literal types for T.
23470-
const constraint = getBaseConstraintOfType(contextualType) || emptyObjectType;
23471+
const constraint = getBaseConstraintOfType(contextualType) || unknownType;
2347123472
return maybeTypeOfKind(constraint, TypeFlags.String) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) ||
2347223473
maybeTypeOfKind(constraint, TypeFlags.Number) && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) ||
2347323474
maybeTypeOfKind(constraint, TypeFlags.BigInt) && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) ||

tests/baselines/reference/callGenericFunctionWithIncorrectNumberOfTypeArguments.types

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -136,24 +136,24 @@ class C2<T, U> {
136136
}
137137
}
138138
var r6 = (new C2()).f<number>(1, '');
139-
>r6 : {}
140-
>(new C2()).f<number>(1, '') : {}
141-
>(new C2()).f : (x: {}, y: {}) => {}
142-
>(new C2()) : C2<{}, {}>
143-
>new C2() : C2<{}, {}>
139+
>r6 : unknown
140+
>(new C2()).f<number>(1, '') : unknown
141+
>(new C2()).f : (x: unknown, y: unknown) => unknown
142+
>(new C2()) : C2<unknown, unknown>
143+
>new C2() : C2<unknown, unknown>
144144
>C2 : typeof C2
145-
>f : (x: {}, y: {}) => {}
145+
>f : (x: unknown, y: unknown) => unknown
146146
>1 : 1
147147
>'' : ""
148148

149149
var r6b = (new C2()).f<number, string, number>(1, '');
150-
>r6b : {}
151-
>(new C2()).f<number, string, number>(1, '') : {}
152-
>(new C2()).f : (x: {}, y: {}) => {}
153-
>(new C2()) : C2<{}, {}>
154-
>new C2() : C2<{}, {}>
150+
>r6b : unknown
151+
>(new C2()).f<number, string, number>(1, '') : unknown
152+
>(new C2()).f : (x: unknown, y: unknown) => unknown
153+
>(new C2()) : C2<unknown, unknown>
154+
>new C2() : C2<unknown, unknown>
155155
>C2 : typeof C2
156-
>f : (x: {}, y: {}) => {}
156+
>f : (x: unknown, y: unknown) => unknown
157157
>1 : 1
158158
>'' : ""
159159

tests/baselines/reference/callGenericFunctionWithZeroTypeArguments.types

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,13 @@ class C2<T> {
8383
}
8484
}
8585
var r6 = (new C2()).f(1);
86-
>r6 : {}
87-
>(new C2()).f(1) : {}
88-
>(new C2()).f : (x: {}) => {}
89-
>(new C2()) : C2<{}>
90-
>new C2() : C2<{}>
86+
>r6 : unknown
87+
>(new C2()).f(1) : unknown
88+
>(new C2()).f : (x: unknown) => unknown
89+
>(new C2()) : C2<unknown>
90+
>new C2() : C2<unknown>
9191
>C2 : typeof C2
92-
>f : (x: {}) => {}
92+
>f : (x: unknown) => unknown
9393
>1 : 1
9494

9595
interface I2<T> {

0 commit comments

Comments
 (0)