Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the default type parameter constraints and defaults to unknown from {} #30637

Merged
merged 7 commits into from
Apr 4, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 23 additions & 22 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7330,7 +7330,7 @@ namespace ts {
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
const constraint = getConstraintTypeFromMappedType(declaredType);
const extendedConstraint = constraint && constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : unknownType;
}
}
return type.modifiersType;
Expand Down Expand Up @@ -7773,7 +7773,7 @@ namespace ts {
* type itself. Note that the apparent type of a union type is the union type itself.
*/
function getApparentType(type: Type): Type {
const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || emptyObjectType : type;
const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || (strictNullChecks ? unknownType : emptyObjectType) : type;
weswigham marked this conversation as resolved.
Show resolved Hide resolved
return getObjectFlags(t) & ObjectFlags.Mapped ? getApparentTypeOfMappedType(<MappedType>t) :
t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(<IntersectionType>t) :
t.flags & TypeFlags.StringLike ? globalStringType :
Expand All @@ -7783,6 +7783,7 @@ namespace ts {
t.flags & TypeFlags.ESSymbolLike ? getGlobalESSymbolType(/*reportErrors*/ languageVersion >= ScriptTarget.ES2015) :
t.flags & TypeFlags.NonPrimitive ? emptyObjectType :
t.flags & TypeFlags.Index ? keyofConstraintType :
t.flags & TypeFlags.Unknown && !strictNullChecks ? emptyObjectType :
t;
}

Expand Down Expand Up @@ -8106,7 +8107,7 @@ namespace ts {
const baseDefaultType = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
for (let i = numTypeArguments; i < numTypeParameters; i++) {
let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) {
if (isJavaScriptImplicitAny && defaultType && (isTypeIdenticalTo(defaultType, unknownType) || isTypeIdenticalTo(defaultType, emptyObjectType))) {
defaultType = anyType;
}
result[i] = defaultType ? instantiateType(defaultType, createTypeMapper(typeParameters!, result)) : baseDefaultType;
Expand Down Expand Up @@ -8485,7 +8486,7 @@ namespace ts {
const typeParameters = signature.typeParameters;
if (typeParameters) {
const typeEraser = createTypeEraser(typeParameters);
const baseConstraints = map(typeParameters, tp => instantiateType(getBaseConstraintOfType(tp), typeEraser) || emptyObjectType);
const baseConstraints = map(typeParameters, tp => instantiateType(getBaseConstraintOfType(tp), typeEraser) || unknownType);
return instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true);
}
return signature;
Expand Down Expand Up @@ -10799,7 +10800,7 @@ namespace ts {
* This is used during inference when instantiating type parameter defaults.
*/
function createBackreferenceMapper(context: InferenceContext, index: number): TypeMapper {
return t => findIndex(context.inferences, info => info.typeParameter === t) >= index ? emptyObjectType : t;
return t => findIndex(context.inferences, info => info.typeParameter === t) >= index ? unknownType : t;
}

function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper;
Expand Down Expand Up @@ -11346,7 +11347,7 @@ namespace ts {
function isTypeDerivedFrom(source: Type, target: Type): boolean {
return source.flags & TypeFlags.Union ? every((<UnionType>source).types, t => isTypeDerivedFrom(t, target)) :
target.flags & TypeFlags.Union ? some((<UnionType>target).types, t => isTypeDerivedFrom(source, t)) :
source.flags & TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || emptyObjectType, target) :
source.flags & TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || unknownType, target) :
target === globalObjectType ? !!(source.flags & (TypeFlags.Object | TypeFlags.NonPrimitive)) :
target === globalFunctionType ? !!(source.flags & TypeFlags.Object) && isFunctionObjectType(source as ObjectType) :
hasBaseType(source, getTargetType(target));
Expand Down Expand Up @@ -13349,7 +13350,7 @@ namespace ts {
return indexTypesIdenticalTo(source, target, kind);
}
const targetInfo = getIndexInfoOfType(target, kind);
if (!targetInfo || targetInfo.type.flags & TypeFlags.AnyOrUnknown && !sourceIsPrimitive) {
if (!targetInfo || targetInfo.type.flags & TypeFlags.Any && !sourceIsPrimitive) {
// Index signature of type any permits assignment from everything but primitives
return Ternary.True;
}
Expand Down Expand Up @@ -14500,7 +14501,7 @@ namespace ts {
const templateType = getTemplateTypeFromMappedType(target);
const inference = createInferenceInfo(typeParameter);
inferTypes([inference], sourceType, templateType);
return getTypeFromInference(inference) || emptyObjectType;
return getTypeFromInference(inference) || unknownType;
}

function* getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean) {
Expand Down Expand Up @@ -15099,7 +15100,7 @@ namespace ts {
}

function getDefaultTypeArgumentType(isInJavaScriptFile: boolean): Type {
return isInJavaScriptFile ? anyType : emptyObjectType;
return isInJavaScriptFile ? anyType : unknownType;
}

function getInferredTypes(context: InferenceContext): Type[] {
Expand Down Expand Up @@ -15443,7 +15444,7 @@ namespace ts {
return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
}
if (flags & TypeFlags.Instantiable) {
return getTypeFacts(getBaseConstraintOfType(type) || emptyObjectType);
return getTypeFacts(getBaseConstraintOfType(type) || unknownType);
}
if (flags & TypeFlags.UnionOrIntersection) {
return getTypeFactsOfTypes((<UnionOrIntersectionType>type).types);
Expand Down Expand Up @@ -16754,7 +16755,7 @@ namespace ts {
}

function typeHasNullableConstraint(type: Type) {
return type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || emptyObjectType, TypeFlags.Nullable);
return type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.Nullable);
}

function getConstraintForLocation(type: Type, node: Node): Type;
Expand Down Expand Up @@ -18204,7 +18205,7 @@ namespace ts {
}

function getJsxPropsTypeFromCallSignature(sig: Signature, context: JsxOpeningLikeElement) {
let propsType = getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType);
let propsType = getTypeOfFirstParameterOfSignatureWithFallback(sig, unknownType);
propsType = getJsxManagedAttributesFromLocatedAttributes(context, getJsxNamespaceAt(context), propsType);
const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes, context);
if (intrinsicAttribs !== errorType) {
Expand Down Expand Up @@ -18278,7 +18279,7 @@ namespace ts {
const forcedLookupLocation = getJsxElementPropertiesName(ns);
let attributesType = forcedLookupLocation === undefined
// If there is no type ElementAttributesProperty, return the type of the first parameter of the signature, which should be the props type
? getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType)
? getTypeOfFirstParameterOfSignatureWithFallback(sig, unknownType)
: forcedLookupLocation === ""
// If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead
? getReturnTypeOfSignature(sig)
Expand All @@ -18290,7 +18291,7 @@ namespace ts {
if (!!forcedLookupLocation && !!length(context.attributes.properties)) {
error(context, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(forcedLookupLocation));
}
return emptyObjectType;
return unknownType;
}

attributesType = getJsxManagedAttributesFromLocatedAttributes(context, ns, attributesType);
Expand Down Expand Up @@ -19501,7 +19502,7 @@ namespace ts {
undefinedDiagnostic?: DiagnosticMessage,
nullOrUndefinedDiagnostic?: DiagnosticMessage
): Type {
if (type.flags & TypeFlags.Unknown) {
if (strictNullChecks && type.flags & TypeFlags.Unknown) {
weswigham marked this conversation as resolved.
Show resolved Hide resolved
error(node, Diagnostics.Object_is_of_type_unknown);
return errorType;
}
Expand Down Expand Up @@ -21992,7 +21993,7 @@ namespace ts {
const decl = parameter.valueDeclaration as ParameterDeclaration;
if (decl.name.kind !== SyntaxKind.Identifier) {
// if inference didn't come up with anything but {}, fall back to the binding pattern if present.
if (links.type === emptyObjectType) {
if (links.type === unknownType) {
links.type = getTypeFromBindingPattern(decl.name);
}
assignBindingElementTypes(decl.name);
Expand All @@ -22005,28 +22006,28 @@ namespace ts {
const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
if (globalPromiseType !== emptyGenericType) {
// if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
promisedType = getAwaitedType(promisedType) || emptyObjectType;
promisedType = getAwaitedType(promisedType) || unknownType;
return createTypeReference(globalPromiseType, [promisedType]);
}

return emptyObjectType;
return unknownType;
}

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

return emptyObjectType;
return unknownType;
}

function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall, promisedType: Type) {
const promiseType = createPromiseType(promisedType);
if (promiseType === emptyObjectType) {
if (promiseType === unknownType) {
error(func, isImportCall(func) ?
Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option :
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);
Expand Down Expand Up @@ -23459,7 +23460,7 @@ namespace ts {
// If the contextual type is a type variable constrained to a primitive type, consider
// this a literal context for literals of that primitive type. For example, given a
// type parameter 'T extends string', infer string literal types for T.
const constraint = getBaseConstraintOfType(contextualType) || emptyObjectType;
const constraint = getBaseConstraintOfType(contextualType) || unknownType;
return maybeTypeOfKind(constraint, TypeFlags.String) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) ||
maybeTypeOfKind(constraint, TypeFlags.Number) && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) ||
maybeTypeOfKind(constraint, TypeFlags.BigInt) && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,24 +136,24 @@ class C2<T, U> {
}
}
var r6 = (new C2()).f<number>(1, '');
>r6 : {}
>(new C2()).f<number>(1, '') : {}
>(new C2()).f : (x: {}, y: {}) => {}
>(new C2()) : C2<{}, {}>
>new C2() : C2<{}, {}>
>r6 : unknown
>(new C2()).f<number>(1, '') : unknown
>(new C2()).f : (x: unknown, y: unknown) => unknown
>(new C2()) : C2<unknown, unknown>
>new C2() : C2<unknown, unknown>
>C2 : typeof C2
>f : (x: {}, y: {}) => {}
>f : (x: unknown, y: unknown) => unknown
>1 : 1
>'' : ""

var r6b = (new C2()).f<number, string, number>(1, '');
>r6b : {}
>(new C2()).f<number, string, number>(1, '') : {}
>(new C2()).f : (x: {}, y: {}) => {}
>(new C2()) : C2<{}, {}>
>new C2() : C2<{}, {}>
>r6b : unknown
>(new C2()).f<number, string, number>(1, '') : unknown
>(new C2()).f : (x: unknown, y: unknown) => unknown
>(new C2()) : C2<unknown, unknown>
>new C2() : C2<unknown, unknown>
>C2 : typeof C2
>f : (x: {}, y: {}) => {}
>f : (x: unknown, y: unknown) => unknown
>1 : 1
>'' : ""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ class C2<T> {
}
}
var r6 = (new C2()).f(1);
>r6 : {}
>(new C2()).f(1) : {}
>(new C2()).f : (x: {}) => {}
>(new C2()) : C2<{}>
>new C2() : C2<{}>
>r6 : unknown
>(new C2()).f(1) : unknown
>(new C2()).f : (x: unknown) => unknown
>(new C2()) : C2<unknown>
>new C2() : C2<unknown>
>C2 : typeof C2
>f : (x: {}) => {}
>f : (x: unknown) => unknown
>1 : 1

interface I2<T> {
Expand Down
Loading