Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
54 changes: 36 additions & 18 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8738,7 +8738,7 @@ func (c *Checker) chooseOverload(s *CallState, relation *Relation) *Signature {
if inferenceContext != nil {
inferredTypeParameters = inferenceContext.inferredTypeParameters
}
checkCandidate = c.getSignatureInstantiation(candidate, typeArgumentTypes, inferredTypeParameters)
checkCandidate = c.getSignatureInstantiation(candidate, typeArgumentTypes, ast.IsInJSFile(candidate.declaration), inferredTypeParameters)
// If the original signature has a generic rest type, instantiation may produce a
// signature with different arity and we need to perform another arity check.
if c.getNonArrayRestType(candidate) != nil && !c.hasCorrectArity(s.node, s.args, checkCandidate, s.signatureHelpTrailingComma) {
Expand All @@ -8760,7 +8760,7 @@ func (c *Checker) chooseOverload(s *CallState, relation *Relation) *Signature {
s.argCheckMode = CheckModeNormal
if inferenceContext != nil {
typeArgumentTypes := c.instantiateTypes(c.inferTypeArguments(s.node, candidate, s.args, s.argCheckMode, inferenceContext), inferenceContext.mapper)
checkCandidate = c.getSignatureInstantiation(candidate, typeArgumentTypes, inferenceContext.inferredTypeParameters)
checkCandidate = c.getSignatureInstantiation(candidate, typeArgumentTypes, ast.IsInJSFile(candidate.declaration), inferenceContext.inferredTypeParameters)
// If the original signature has a generic rest type, instantiation may produce a
// signature with different arity and we need to perform another arity check.
if c.getNonArrayRestType(candidate) != nil && !c.hasCorrectArity(s.node, s.args, checkCandidate, s.signatureHelpTrailingComma) {
Expand Down Expand Up @@ -8906,8 +8906,9 @@ func (c *Checker) hasCorrectTypeArgumentArity(signature *Signature, typeArgument
}

func (c *Checker) checkTypeArguments(signature *Signature, typeArgumentNodes []*ast.Node, reportErrors bool, headMessage *diagnostics.Message) []*Type {
isJavaScript := ast.IsInJSFile(signature.declaration)
typeParameters := signature.typeParameters
typeArgumentTypes := c.fillMissingTypeArguments(core.Map(typeArgumentNodes, c.getTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters))
typeArgumentTypes := c.fillMissingTypeArguments(core.Map(typeArgumentNodes, c.getTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters), isJavaScript)
var mapper *TypeMapper
for i := range typeArgumentNodes {
// Debug.assert(typeParameters[i] != nil, "Should not call checkTypeArguments with too many type arguments")
Expand Down Expand Up @@ -10162,7 +10163,7 @@ func (c *Checker) getInstantiationExpressionType(exprType *Type, node *ast.Node)
return core.SameMap(applicableSignatures, func(sig *Signature) *Signature {
typeArgumentTypes := c.checkTypeArguments(sig, typeArguments.Nodes, true /*reportErrors*/, nil)
if typeArgumentTypes != nil {
return c.getSignatureInstantiation(sig, typeArgumentTypes, nil)
return c.getSignatureInstantiation(sig, typeArgumentTypes, ast.IsInJSFile(sig.declaration), nil)
}
return sig
})
Expand Down Expand Up @@ -18328,7 +18329,7 @@ func (c *Checker) getInstantiatedConstructorsForTypeArguments(t *Type, typeArgum
typeArguments := core.Map(typeArgumentNodes, c.getTypeFromTypeNode)
return core.SameMap(signatures, func(sig *Signature) *Signature {
if len(sig.typeParameters) != 0 {
return c.getSignatureInstantiation(sig, typeArguments, nil)
return c.getSignatureInstantiation(sig, typeArguments, ast.IsInJSFile(location), nil)
}
return sig
})
Expand All @@ -18341,8 +18342,8 @@ func (c *Checker) getConstructorsForTypeArguments(t *Type, typeArgumentNodes []*
})
}

func (c *Checker) getSignatureInstantiation(sig *Signature, typeArguments []*Type, inferredTypeParameters []*Type) *Signature {
instantiatedSignature := c.getSignatureInstantiationWithoutFillingInTypeArguments(sig, c.fillMissingTypeArguments(typeArguments, sig.typeParameters, c.getMinTypeArgumentCount(sig.typeParameters)))
func (c *Checker) getSignatureInstantiation(sig *Signature, typeArguments []*Type, isJavaScript bool, inferredTypeParameters []*Type) *Signature {
instantiatedSignature := c.getSignatureInstantiationWithoutFillingInTypeArguments(sig, c.fillMissingTypeArguments(typeArguments, sig.typeParameters, c.getMinTypeArgumentCount(sig.typeParameters), isJavaScript))
if len(inferredTypeParameters) != 0 {
returnSignature := c.getSingleCallOrConstructSignature(c.getReturnTypeOfSignature(instantiatedSignature))
if returnSignature != nil {
Expand Down Expand Up @@ -18480,12 +18481,13 @@ func (c *Checker) createCanonicalSignature(signature *Signature) *Signature {
// where different generations of the same type parameter are in scope). This leads to a lot of new type
// identities, and potentially a lot of work comparing those identities, so here we create an instantiation
// that uses the original type identities for all unconstrained type parameters.
return c.getSignatureInstantiation(signature, core.Map(signature.typeParameters, func(tp *Type) *Type {
typeArguments := core.Map(signature.typeParameters, func(tp *Type) *Type {
if tp.Target() != nil && c.getConstraintOfTypeParameter(tp.Target()) == nil {
return tp.Target()
}
return tp
}), nil)
})
return c.getSignatureInstantiation(signature, typeArguments, ast.IsInJSFile(signature.declaration), nil /*inferredTypeParameters*/)
}

func (c *Checker) getBaseSignature(signature *Signature) *Signature {
Expand Down Expand Up @@ -18545,7 +18547,7 @@ func (c *Checker) instantiateSignatureInContextOf(signature *Signature, contextu
c.inferTypes(context.inferences, source, target, InferencePriorityReturnType, false)
})
}
return c.getSignatureInstantiation(signature, c.getInferredTypes(context), nil)
return c.getSignatureInstantiation(signature, c.getInferredTypes(context), ast.IsInJSFile(contextualSignature.declaration), nil /*inferredTypeParameters*/)
}

func (c *Checker) resolveBaseTypesOfInterface(t *Type) {
Expand Down Expand Up @@ -19866,16 +19868,17 @@ func (c *Checker) getDefaultConstructSignatures(classType *Type) []*Signature {
return []*Signature{c.newSignature(flags, nil, classType.AsInterfaceType().LocalTypeParameters(), nil, nil, classType, nil, 0)}
}
baseTypeNode := getBaseTypeNodeOfClass(classType)
isJavaScript := declaration != nil && ast.IsInJSFile(declaration)
typeArguments := c.getTypeArgumentsFromNode(baseTypeNode)
typeArgCount := len(typeArguments)
var result []*Signature
for _, baseSig := range baseSignatures {
minTypeArgumentCount := c.getMinTypeArgumentCount(baseSig.typeParameters)
typeParamCount := len(baseSig.typeParameters)
if typeArgCount >= minTypeArgumentCount && typeArgCount <= typeParamCount {
if isJavaScript || typeArgCount >= minTypeArgumentCount && typeArgCount <= typeParamCount {
var sig *Signature
if typeParamCount != 0 {
sig = c.createSignatureInstantiation(baseSig, c.fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount))
sig = c.createSignatureInstantiation(baseSig, c.fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, isJavaScript))
} else {
sig = c.cloneSignature(baseSig)
}
Expand Down Expand Up @@ -20969,7 +20972,7 @@ func (c *Checker) getTypeArguments(t *Type) []*Type {
}

func (c *Checker) getEffectiveTypeArguments(node *ast.Node, typeParameters []*Type) []*Type {
return c.fillMissingTypeArguments(core.Map(node.TypeArguments(), c.getTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters))
return c.fillMissingTypeArguments(core.Map(node.TypeArguments(), c.getTypeFromTypeNode), typeParameters, c.getMinTypeArgumentCount(typeParameters), ast.IsInJSFile(node))
}

// Gets the minimum number of type arguments needed to satisfy all non-optional type parameters.
Expand All @@ -20989,7 +20992,7 @@ func (c *Checker) hasTypeParameterDefault(t *Type) bool {
})
}

func (c *Checker) fillMissingTypeArguments(typeArguments []*Type, typeParameters []*Type, minTypeArgumentCount int) []*Type {
func (c *Checker) fillMissingTypeArguments(typeArguments []*Type, typeParameters []*Type, minTypeArgumentCount int, isJavaScriptImplicitAny bool) []*Type {
numTypeParameters := len(typeParameters)
if numTypeParameters == 0 {
return nil
Expand All @@ -21002,19 +21005,32 @@ func (c *Checker) fillMissingTypeArguments(typeArguments []*Type, typeParameters
for i := numTypeArguments; i < numTypeParameters; i++ {
result[i] = c.errorType
}
baseDefaultType := c.getDefaultTypeArgumentType(isJavaScriptImplicitAny)
for i := numTypeArguments; i < numTypeParameters; i++ {
defaultType := c.getDefaultFromTypeParameter(typeParameters[i])

if isJavaScriptImplicitAny && defaultType != nil && (c.isTypeIdenticalTo(defaultType, c.unknownType) || c.isTypeIdenticalTo(defaultType, c.emptyObjectType)) {
defaultType = c.anyType
}

if defaultType != nil {
result[i] = c.instantiateType(defaultType, newTypeMapper(typeParameters, result))
} else {
result[i] = c.unknownType
result[i] = baseDefaultType
}
}
return result
}
return typeArguments
}

func (c *Checker) getDefaultTypeArgumentType(isInJavaScriptFile bool) *Type {
if isInJavaScriptFile {
return c.anyType
}
return c.unknownType
}

// Gets the default type for a type parameter. If the type parameter is the result of an instantiation,
// this gets the instantiated default type of its target. If the type parameter has no default type or
// the default is circular, `undefined` is returned.
Expand Down Expand Up @@ -22067,7 +22083,9 @@ func (c *Checker) getTypeFromClassOrInterfaceReference(node *ast.Node, symbol *a
if len(typeParameters) != 0 {
numTypeArguments := len(node.TypeArguments())
minTypeArgumentCount := c.getMinTypeArgumentCount(typeParameters)
if numTypeArguments < minTypeArgumentCount || numTypeArguments > len(typeParameters) {
isJs := ast.IsInJSFile(node)
isJsImplicitAny := !c.noImplicitAny && isJs
if !isJsImplicitAny && (numTypeArguments < minTypeArgumentCount || numTypeArguments > len(typeParameters)) {
message := diagnostics.Generic_type_0_requires_1_type_argument_s
if minTypeArgumentCount < len(typeParameters) {
message = diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments
Expand All @@ -22083,7 +22101,7 @@ func (c *Checker) getTypeFromClassOrInterfaceReference(node *ast.Node, symbol *a
// In a type reference, the outer type parameters of the referenced class or interface are automatically
// supplied as type arguments and the type reference only specifies arguments for the local type parameters
// of the class or interface.
localTypeArguments := c.fillMissingTypeArguments(c.getTypeArgumentsFromNode(node), typeParameters, minTypeArgumentCount)
localTypeArguments := c.fillMissingTypeArguments(c.getTypeArgumentsFromNode(node), typeParameters, minTypeArgumentCount, isJs)
typeArguments := append(d.OuterTypeParameters(), localTypeArguments...)
return c.createTypeReference(t, typeArguments)
}
Expand Down Expand Up @@ -22524,7 +22542,7 @@ func (c *Checker) getTypeAliasInstantiation(symbol *ast.Symbol, typeArguments []
key := getTypeAliasInstantiationKey(typeArguments, alias)
instantiation := links.instantiations[key]
if instantiation == nil {
mapper := newTypeMapper(typeParameters, c.fillMissingTypeArguments(typeArguments, typeParameters, c.getMinTypeArgumentCount(typeParameters)))
mapper := newTypeMapper(typeParameters, c.fillMissingTypeArguments(typeArguments, typeParameters, c.getMinTypeArgumentCount(typeParameters), ast.IsInJSFile(symbol.ValueDeclaration)))
instantiation = c.instantiateTypeWithAlias(t, mapper, alias)
links.instantiations[key] = instantiation
}
Expand Down
4 changes: 2 additions & 2 deletions internal/checker/inference.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ func (c *Checker) inferFromTypes(n *InferenceState, source *Type, target *Type)
// Simply infer from source type arguments to target type arguments, with defaults applied.
params := c.typeAliasLinks.Get(source.alias.symbol).typeParameters
minParams := c.getMinTypeArgumentCount(params)
sourceTypes := c.fillMissingTypeArguments(source.alias.typeArguments, params, minParams)
targetTypes := c.fillMissingTypeArguments(target.alias.typeArguments, params, minParams)
sourceTypes := c.fillMissingTypeArguments(source.alias.typeArguments, params, minParams, ast.IsInJSFile(source.alias.symbol.ValueDeclaration))
targetTypes := c.fillMissingTypeArguments(target.alias.typeArguments, params, minParams, ast.IsInJSFile(source.alias.symbol.ValueDeclaration))
Comment thread
DanielRosenwasser marked this conversation as resolved.
Outdated
c.inferFromTypeArguments(n, sourceTypes, targetTypes, c.getAliasVariances(source.alias.symbol))
}
// And if there weren't any type arguments, there's no reason to run inference as the types must be the same.
Expand Down
16 changes: 8 additions & 8 deletions internal/checker/jsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -952,16 +952,16 @@ func (c *Checker) getJsxPropsTypeFromClassType(sig *Signature, context *ast.Node
// Props is of type 'any' or unknown
return attributesType
}
// Normal case -- add in IntrinsicClassElements<T> and IntrinsicElements
// Normal case -- add in IntrinsicClassAttributes<T> and IntrinsicAttributes
apparentAttributesType := attributesType
intrinsicClassAttribs := c.getJsxType(JsxNames.IntrinsicClassAttributes, context)
if !c.isErrorType(intrinsicClassAttribs) {
typeParams := c.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol)
hostClassType := c.getReturnTypeOfSignature(sig)
var libraryManagedAttributeType *Type
if typeParams != nil {
// apply JSX.IntrinsicClassElements<hostClassType, ...>
inferredArgs := c.fillMissingTypeArguments([]*Type{hostClassType}, typeParams, c.getMinTypeArgumentCount(typeParams))
// apply JSX.IntrinsicClassAttributes<hostClassType, ...>
inferredArgs := c.fillMissingTypeArguments([]*Type{hostClassType}, typeParams, c.getMinTypeArgumentCount(typeParams), ast.IsInJSFile(context))
libraryManagedAttributeType = c.instantiateType(intrinsicClassAttribs, newTypeMapper(typeParams, inferredArgs))
} else {
libraryManagedAttributeType = intrinsicClassAttribs
Expand Down Expand Up @@ -1008,29 +1008,29 @@ func (c *Checker) getJsxManagedAttributesFromLocatedAttributes(context *ast.Node
managedSym := c.getJsxLibraryManagedAttributes(ns)
if managedSym != nil {
ctorType := c.getStaticTypeOfReferencedJsxConstructor(context)
result := c.instantiateAliasOrInterfaceWithDefaults(managedSym, []*Type{ctorType, attributesType})
result := c.instantiateAliasOrInterfaceWithDefaults(managedSym, []*Type{ctorType, attributesType}, ast.IsInJSFile(context))
if result != nil {
return result
}
}
return attributesType
}

func (c *Checker) instantiateAliasOrInterfaceWithDefaults(managedSym *ast.Symbol, typeArguments []*Type) *Type {
func (c *Checker) instantiateAliasOrInterfaceWithDefaults(managedSym *ast.Symbol, typeArguments []*Type, inJavaScript bool) *Type {
declaredManagedType := c.getDeclaredTypeOfSymbol(managedSym)
// fetches interface type, or initializes symbol links type parmaeters
if managedSym.Flags&ast.SymbolFlagsTypeAlias != 0 {
params := c.typeAliasLinks.Get(managedSym).typeParameters
if len(params) >= len(typeArguments) {
args := c.fillMissingTypeArguments(typeArguments, params, len(typeArguments))
args := c.fillMissingTypeArguments(typeArguments, params, len(typeArguments), inJavaScript)
if len(args) == 0 {
return declaredManagedType
}
return c.getTypeAliasInstantiation(managedSym, args, nil)
}
}
if len(declaredManagedType.AsInterfaceType().TypeParameters()) >= len(typeArguments) {
args := c.fillMissingTypeArguments(typeArguments, declaredManagedType.AsInterfaceType().TypeParameters(), len(typeArguments))
args := c.fillMissingTypeArguments(typeArguments, declaredManagedType.AsInterfaceType().TypeParameters(), len(typeArguments), inJavaScript)
return c.createTypeReference(declaredManagedType, args)
}
return nil
Expand Down Expand Up @@ -1272,7 +1272,7 @@ func (c *Checker) getJsxElementTypeTypeAt(location *ast.Node) *Type {
if sym == nil {
return nil
}
t := c.instantiateAliasOrInterfaceWithDefaults(sym, nil)
t := c.instantiateAliasOrInterfaceWithDefaults(sym, nil, ast.IsInJSFile(location))
if t == nil || c.isErrorType(t) {
return nil
}
Expand Down
4 changes: 2 additions & 2 deletions internal/checker/relater.go
Original file line number Diff line number Diff line change
Expand Up @@ -3327,8 +3327,8 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo
}
params := r.c.typeAliasLinks.Get(source.alias.symbol).typeParameters
minParams := r.c.getMinTypeArgumentCount(params)
sourceTypes := r.c.fillMissingTypeArguments(source.alias.typeArguments, params, minParams)
targetTypes := r.c.fillMissingTypeArguments(target.alias.typeArguments, params, minParams)
sourceTypes := r.c.fillMissingTypeArguments(source.alias.typeArguments, params, minParams, ast.IsInJSFile(source.alias.symbol.ValueDeclaration))
targetTypes := r.c.fillMissingTypeArguments(target.alias.typeArguments, params, minParams, ast.IsInJSFile(source.alias.symbol.ValueDeclaration))
Comment thread
DanielRosenwasser marked this conversation as resolved.
Outdated
varianceResult, ok := relateVariances(sourceTypes, targetTypes, variances, intersectionState)
if ok {
return varianceResult
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { Foo } from "./library";

export class MyFoo extends Foo {
>MyFoo : MyFoo
>Foo : Foo<{}, {}>
>Foo : Foo<any, any>

member;
>member : any
Expand Down Expand Up @@ -50,23 +50,23 @@ export class TypedFoo extends MyFoo {

this.props.x;
>this.props.x : any
>this.props : {}
>this.props : any
>this : this
>props : {}
>props : any
>x : any

this.props.y;
>this.props.y : any
>this.props : {}
>this.props : any
>this : this
>props : {}
>props : any
>y : any

this.state.value;
>this.state.value : any
>this.state : {}
>this.state : any
>this : this
>state : {}
>state : any
>value : any

this.member;
Expand Down

This file was deleted.

Loading
Loading