mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-10 15:25:54 -06:00
Port fixes from master into release-2.5 (#18361)
* Test: parsing of two-line @typedef jsdoc * Fix forEachChild's visit of JSDocTypedefTag Also remove JSDocTypeLiteral.jsdocTypeTag, which made no sense since it was only useful when storing information for its parent `@typedef` tag. * Update baselines * Inline variable to aid control flow * Improved caching scheme for anonymous types * Fix signature help * Optimize caching of type literals * Accept new baselines * Fix linting errors * Use canonicalized forms when comparing signatures * Minor changes * Document ThrottledOperations.schedule * Limit the number of unanswered typings installer requests If we send them all at once, we (apparently) hit a buffer limit in the node IPC channel and both TS Server and the typings installer become unresponsive. * Fix lint issues * Add explanatory comment
This commit is contained in:
parent
c476a08188
commit
1c7a29eeb3
@ -4788,22 +4788,39 @@ namespace ts {
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
// Appends the outer type parameters of a node to a set of type parameters and returns the resulting set. The function
|
||||
// allocates a new array if the input type parameter set is undefined, but otherwise it modifies the set in-place and
|
||||
// returns the same array.
|
||||
function appendOuterTypeParameters(typeParameters: TypeParameter[], node: Node): TypeParameter[] {
|
||||
// Return the outer type parameters of a node or undefined if the node has no outer type parameters.
|
||||
function getOuterTypeParameters(node: Node, includeThisTypes?: boolean): TypeParameter[] {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
if (!node) {
|
||||
return typeParameters;
|
||||
return undefined;
|
||||
}
|
||||
if (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression ||
|
||||
node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression ||
|
||||
node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.ArrowFunction) {
|
||||
const declarations = (<ClassLikeDeclaration | FunctionLikeDeclaration>node).typeParameters;
|
||||
if (declarations) {
|
||||
return appendTypeParameters(appendOuterTypeParameters(typeParameters, node), declarations);
|
||||
}
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
case SyntaxKind.MappedType:
|
||||
const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes);
|
||||
if (node.kind === SyntaxKind.MappedType) {
|
||||
return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((<MappedTypeNode>node).typeParameter)));
|
||||
}
|
||||
const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(<DeclarationWithTypeParameters>node) || emptyArray);
|
||||
const thisType = includeThisTypes &&
|
||||
(node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration) &&
|
||||
getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node)).thisType;
|
||||
return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4811,7 +4828,7 @@ namespace ts {
|
||||
// The outer type parameters are those defined by enclosing generic classes, methods, or functions.
|
||||
function getOuterTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] {
|
||||
const declaration = symbol.flags & SymbolFlags.Class ? symbol.valueDeclaration : getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration);
|
||||
return appendOuterTypeParameters(/*typeParameters*/ undefined, declaration);
|
||||
return getOuterTypeParameters(declaration);
|
||||
}
|
||||
|
||||
// The local type parameters are the combined set of type parameters from all declarations of the class,
|
||||
@ -6614,11 +6631,30 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getErasedSignature(signature: Signature): Signature {
|
||||
if (!signature.typeParameters) return signature;
|
||||
if (!signature.erasedSignatureCache) {
|
||||
signature.erasedSignatureCache = instantiateSignature(signature, createTypeEraser(signature.typeParameters), /*eraseTypeParameters*/ true);
|
||||
}
|
||||
return signature.erasedSignatureCache;
|
||||
return signature.typeParameters ?
|
||||
signature.erasedSignatureCache || (signature.erasedSignatureCache = createErasedSignature(signature)) :
|
||||
signature;
|
||||
}
|
||||
|
||||
function createErasedSignature(signature: Signature) {
|
||||
// Create an instantiation of the signature where all type arguments are the any type.
|
||||
return instantiateSignature(signature, createTypeEraser(signature.typeParameters), /*eraseTypeParameters*/ true);
|
||||
}
|
||||
|
||||
function getCanonicalSignature(signature: Signature): Signature {
|
||||
return signature.typeParameters ?
|
||||
signature.canonicalSignatureCache || (signature.canonicalSignatureCache = createCanonicalSignature(signature)) :
|
||||
signature;
|
||||
}
|
||||
|
||||
function createCanonicalSignature(signature: Signature) {
|
||||
// Create an instantiation of the signature where each unconstrained type parameter is replaced with
|
||||
// its original. When a generic class or interface is instantiated, each generic method in the class or
|
||||
// interface is instantiated with a fresh set of cloned type parameters (which we need to handle scenarios
|
||||
// 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 getSignatureInstantiation(signature, map(signature.typeParameters, tp => tp.target && !getConstraintOfTypeParameter(tp.target) ? tp.target : tp));
|
||||
}
|
||||
|
||||
function getOrCreateTypeFromSignature(signature: Signature): ObjectType {
|
||||
@ -6799,7 +6835,7 @@ namespace ts {
|
||||
const id = getTypeListId(typeArguments);
|
||||
let instantiation = links.instantiations.get(id);
|
||||
if (!instantiation) {
|
||||
links.instantiations.set(id, instantiation = instantiateTypeNoAlias(type, createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters)))));
|
||||
links.instantiations.set(id, instantiation = instantiateType(type, createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters)))));
|
||||
}
|
||||
return instantiation;
|
||||
}
|
||||
@ -8034,11 +8070,6 @@ namespace ts {
|
||||
return instantiateList(signatures, mapper, instantiateSignature);
|
||||
}
|
||||
|
||||
function instantiateCached<T extends Type>(type: T, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T {
|
||||
const instantiations = mapper.instantiations || (mapper.instantiations = []);
|
||||
return <T>instantiations[type.id] || (instantiations[type.id] = instantiator(type, mapper));
|
||||
}
|
||||
|
||||
function makeUnaryTypeMapper(source: Type, target: Type) {
|
||||
return (t: Type) => t === source ? target : t;
|
||||
}
|
||||
@ -8060,11 +8091,9 @@ namespace ts {
|
||||
|
||||
function createTypeMapper(sources: TypeParameter[], targets: Type[]): TypeMapper {
|
||||
Debug.assert(targets === undefined || sources.length === targets.length);
|
||||
const mapper: TypeMapper = sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) :
|
||||
return sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) :
|
||||
sources.length === 2 ? makeBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) :
|
||||
makeArrayTypeMapper(sources, targets);
|
||||
mapper.mappedTypes = sources;
|
||||
return mapper;
|
||||
makeArrayTypeMapper(sources, targets);
|
||||
}
|
||||
|
||||
function createTypeEraser(sources: TypeParameter[]): TypeMapper {
|
||||
@ -8075,10 +8104,8 @@ namespace ts {
|
||||
* Maps forward-references to later types parameters to the empty object type.
|
||||
* This is used during inference when instantiating type parameter defaults.
|
||||
*/
|
||||
function createBackreferenceMapper(typeParameters: TypeParameter[], index: number) {
|
||||
const mapper: TypeMapper = t => indexOf(typeParameters, t) >= index ? emptyObjectType : t;
|
||||
mapper.mappedTypes = typeParameters;
|
||||
return mapper;
|
||||
function createBackreferenceMapper(typeParameters: TypeParameter[], index: number): TypeMapper {
|
||||
return t => indexOf(typeParameters, t) >= index ? emptyObjectType : t;
|
||||
}
|
||||
|
||||
function isInferenceContext(mapper: TypeMapper): mapper is InferenceContext {
|
||||
@ -8096,15 +8123,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
|
||||
const mapper: TypeMapper = t => instantiateType(mapper1(t), mapper2);
|
||||
mapper.mappedTypes = concatenate(mapper1.mappedTypes, mapper2.mappedTypes);
|
||||
return mapper;
|
||||
return t => instantiateType(mapper1(t), mapper2);
|
||||
}
|
||||
|
||||
function createReplacementMapper(source: Type, target: Type, baseMapper: TypeMapper) {
|
||||
const mapper: TypeMapper = t => t === source ? target : baseMapper(t);
|
||||
mapper.mappedTypes = baseMapper.mappedTypes;
|
||||
return mapper;
|
||||
function createReplacementMapper(source: Type, target: Type, baseMapper: TypeMapper): TypeMapper {
|
||||
return t => t === source ? target : baseMapper(t);
|
||||
}
|
||||
|
||||
function cloneTypeParameter(typeParameter: TypeParameter): TypeParameter {
|
||||
@ -8181,13 +8204,53 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): AnonymousType {
|
||||
const result = <AnonymousType>createObjectType(ObjectFlags.Anonymous | ObjectFlags.Instantiated, type.symbol);
|
||||
result.target = type.objectFlags & ObjectFlags.Instantiated ? type.target : type;
|
||||
result.mapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper, mapper) : mapper;
|
||||
result.aliasSymbol = type.aliasSymbol;
|
||||
result.aliasTypeArguments = instantiateTypes(type.aliasTypeArguments, mapper);
|
||||
return result;
|
||||
function getAnonymousTypeInstantiation(type: AnonymousType, mapper: TypeMapper) {
|
||||
const target = type.objectFlags & ObjectFlags.Instantiated ? type.target : type;
|
||||
const symbol = target.symbol;
|
||||
const links = getSymbolLinks(symbol);
|
||||
let typeParameters = links.typeParameters;
|
||||
if (!typeParameters) {
|
||||
// The first time an anonymous type is instantiated we compute and store a list of the type
|
||||
// parameters that are in scope (and therefore potentially referenced). For type literals that
|
||||
// aren't the right hand side of a generic type alias declaration we optimize by reducing the
|
||||
// set of type parameters to those that are actually referenced somewhere in the literal.
|
||||
const declaration = symbol.declarations[0];
|
||||
const outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true) || emptyArray;
|
||||
typeParameters = symbol.flags & SymbolFlags.TypeLiteral && !target.aliasTypeArguments ?
|
||||
filter(outerTypeParameters, tp => isTypeParameterReferencedWithin(tp, declaration)) :
|
||||
outerTypeParameters;
|
||||
links.typeParameters = typeParameters;
|
||||
if (typeParameters.length) {
|
||||
links.instantiations = createMap<Type>();
|
||||
links.instantiations.set(getTypeListId(typeParameters), target);
|
||||
}
|
||||
}
|
||||
if (typeParameters.length) {
|
||||
// We are instantiating an anonymous type that has one or more type parameters in scope. Apply the
|
||||
// mapper to the type parameters to produce the effective list of type arguments, and compute the
|
||||
// instantiation cache key from the type IDs of the type arguments.
|
||||
const combinedMapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper, mapper) : mapper;
|
||||
const typeArguments = map(typeParameters, combinedMapper);
|
||||
const id = getTypeListId(typeArguments);
|
||||
let result = links.instantiations.get(id);
|
||||
if (!result) {
|
||||
const newMapper = createTypeMapper(typeParameters, typeArguments);
|
||||
result = target.objectFlags & ObjectFlags.Mapped ? instantiateMappedType(<MappedType>target, newMapper) : instantiateAnonymousType(target, newMapper);
|
||||
links.instantiations.set(id, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function isTypeParameterReferencedWithin(tp: TypeParameter, node: Node) {
|
||||
return tp.isThisType ? forEachChild(node, checkThis) : forEachChild(node, checkIdentifier);
|
||||
function checkThis(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.ThisType || forEachChild(node, checkThis);
|
||||
}
|
||||
function checkIdentifier(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.Identifier && isPartOfTypeNode(node) && getTypeFromTypeNode(<TypeNode>node) === tp || forEachChild(node, checkIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
function instantiateMappedType(type: MappedType, mapper: TypeMapper): Type {
|
||||
@ -8204,164 +8267,64 @@ namespace ts {
|
||||
if (typeVariable !== mappedTypeVariable) {
|
||||
return mapType(mappedTypeVariable, t => {
|
||||
if (isMappableType(t)) {
|
||||
return instantiateMappedObjectType(type, createReplacementMapper(typeVariable, t, mapper));
|
||||
return instantiateAnonymousType(type, createReplacementMapper(typeVariable, t, mapper));
|
||||
}
|
||||
return t;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return instantiateMappedObjectType(type, mapper);
|
||||
return instantiateAnonymousType(type, mapper);
|
||||
}
|
||||
|
||||
function isMappableType(type: Type) {
|
||||
return type.flags & (TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.Intersection | TypeFlags.IndexedAccess);
|
||||
}
|
||||
|
||||
function instantiateMappedObjectType(type: MappedType, mapper: TypeMapper): Type {
|
||||
const result = <MappedType>createObjectType(ObjectFlags.Mapped | ObjectFlags.Instantiated, type.symbol);
|
||||
result.declaration = type.declaration;
|
||||
result.mapper = type.mapper ? combineTypeMappers(type.mapper, mapper) : mapper;
|
||||
function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): AnonymousType {
|
||||
const result = <AnonymousType>createObjectType(type.objectFlags | ObjectFlags.Instantiated, type.symbol);
|
||||
if (type.objectFlags & ObjectFlags.Mapped) {
|
||||
(<MappedType>result).declaration = (<MappedType>type).declaration;
|
||||
}
|
||||
result.target = type;
|
||||
result.mapper = mapper;
|
||||
result.aliasSymbol = type.aliasSymbol;
|
||||
result.aliasTypeArguments = instantiateTypes(type.aliasTypeArguments, mapper);
|
||||
return result;
|
||||
}
|
||||
|
||||
function isSymbolInScopeOfMappedTypeParameter(symbol: Symbol, mapper: TypeMapper) {
|
||||
if (!(symbol.declarations && symbol.declarations.length)) {
|
||||
return false;
|
||||
}
|
||||
const mappedTypes = mapper.mappedTypes;
|
||||
// Starting with the parent of the symbol's declaration, check if the mapper maps any of
|
||||
// the type parameters introduced by enclosing declarations. We just pick the first
|
||||
// declaration since multiple declarations will all have the same parent anyway.
|
||||
return !!findAncestor(symbol.declarations[0], node => {
|
||||
if (node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.SourceFile) {
|
||||
return "quit";
|
||||
}
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.IndexSignature:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
const typeParameters = getEffectiveTypeParameterDeclarations(node as DeclarationWithTypeParameters);
|
||||
if (typeParameters) {
|
||||
for (const d of typeParameters) {
|
||||
if (contains(mappedTypes, getDeclaredTypeOfTypeParameter(getSymbolOfNode(d)))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isClassLike(node) || node.kind === SyntaxKind.InterfaceDeclaration) {
|
||||
const thisType = getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node)).thisType;
|
||||
if (thisType && contains(mappedTypes, thisType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.MappedType:
|
||||
if (contains(mappedTypes, getDeclaredTypeOfTypeParameter(getSymbolOfNode((<MappedTypeNode>node).typeParameter)))) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
const func = node as JSDocFunctionType;
|
||||
for (const p of func.parameters) {
|
||||
if (contains(mappedTypes, getTypeOfNode(p))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isTopLevelTypeAlias(symbol: Symbol) {
|
||||
if (symbol.declarations && symbol.declarations.length) {
|
||||
const parentKind = symbol.declarations[0].parent.kind;
|
||||
return parentKind === SyntaxKind.SourceFile || parentKind === SyntaxKind.ModuleBlock;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function instantiateType(type: Type, mapper: TypeMapper): Type {
|
||||
if (type && mapper !== identityMapper) {
|
||||
// If we are instantiating a type that has a top-level type alias, obtain the instantiation through
|
||||
// the type alias instead in order to share instantiations for the same type arguments. This can
|
||||
// dramatically reduce the number of structurally identical types we generate. Note that we can only
|
||||
// perform this optimization for top-level type aliases. Consider:
|
||||
//
|
||||
// function f1<T>(x: T) {
|
||||
// type Foo<X> = { x: X, t: T };
|
||||
// let obj: Foo<T> = { x: x };
|
||||
// return obj;
|
||||
// }
|
||||
// function f2<U>(x: U) { return f1(x); }
|
||||
// let z = f2(42);
|
||||
//
|
||||
// Above, the declaration of f2 has an inferred return type that is an instantiation of f1's Foo<X>
|
||||
// equivalent to { x: U, t: U }. When instantiating this return type, we can't go back to Foo<X>'s
|
||||
// cache because all cached instantiations are of the form { x: ???, t: T }, i.e. they have not been
|
||||
// instantiated for T. Instead, we need to further instantiate the { x: U, t: U } form.
|
||||
if (type.aliasSymbol && isTopLevelTypeAlias(type.aliasSymbol)) {
|
||||
if (type.aliasTypeArguments) {
|
||||
return getTypeAliasInstantiation(type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
|
||||
if (type.flags & TypeFlags.TypeParameter) {
|
||||
return mapper(<TypeParameter>type);
|
||||
}
|
||||
if (type.flags & TypeFlags.Object) {
|
||||
if ((<ObjectType>type).objectFlags & ObjectFlags.Anonymous) {
|
||||
// If the anonymous type originates in a declaration of a function, method, class, or
|
||||
// interface, in an object type literal, or in an object literal expression, we may need
|
||||
// to instantiate the type because it might reference a type parameter.
|
||||
return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ?
|
||||
getAnonymousTypeInstantiation(<AnonymousType>type, mapper) : type;
|
||||
}
|
||||
if ((<ObjectType>type).objectFlags & ObjectFlags.Mapped) {
|
||||
return getAnonymousTypeInstantiation(<MappedType>type, mapper);
|
||||
}
|
||||
if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) {
|
||||
return createTypeReference((<TypeReference>type).target, instantiateTypes((<TypeReference>type).typeArguments, mapper));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
return instantiateTypeNoAlias(type, mapper);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function instantiateTypeNoAlias(type: Type, mapper: TypeMapper): Type {
|
||||
if (type.flags & TypeFlags.TypeParameter) {
|
||||
return mapper(<TypeParameter>type);
|
||||
}
|
||||
if (type.flags & TypeFlags.Object) {
|
||||
if ((<ObjectType>type).objectFlags & ObjectFlags.Anonymous) {
|
||||
// If the anonymous type originates in a declaration of a function, method, class, or
|
||||
// interface, in an object type literal, or in an object literal expression, we may need
|
||||
// to instantiate the type because it might reference a type parameter. We skip instantiation
|
||||
// if none of the type parameters that are in scope in the type's declaration are mapped by
|
||||
// the given mapper, however we can only do that analysis if the type isn't itself an
|
||||
// instantiation.
|
||||
return type.symbol &&
|
||||
type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) &&
|
||||
((<ObjectType>type).objectFlags & ObjectFlags.Instantiated || isSymbolInScopeOfMappedTypeParameter(type.symbol, mapper)) ?
|
||||
instantiateCached(type, mapper, instantiateAnonymousType) : type;
|
||||
if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) {
|
||||
return getUnionType(instantiateTypes((<UnionType>type).types, mapper), /*subtypeReduction*/ false, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
|
||||
}
|
||||
if ((<ObjectType>type).objectFlags & ObjectFlags.Mapped) {
|
||||
return instantiateCached(type, mapper, instantiateMappedType);
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
return getIntersectionType(instantiateTypes((<IntersectionType>type).types, mapper), type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
|
||||
}
|
||||
if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) {
|
||||
return createTypeReference((<TypeReference>type).target, instantiateTypes((<TypeReference>type).typeArguments, mapper));
|
||||
if (type.flags & TypeFlags.Index) {
|
||||
return getIndexType(instantiateType((<IndexType>type).type, mapper));
|
||||
}
|
||||
if (type.flags & TypeFlags.IndexedAccess) {
|
||||
return getIndexedAccessType(instantiateType((<IndexedAccessType>type).objectType, mapper), instantiateType((<IndexedAccessType>type).indexType, mapper));
|
||||
}
|
||||
}
|
||||
if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) {
|
||||
return getUnionType(instantiateTypes((<UnionType>type).types, mapper), /*subtypeReduction*/ false, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
|
||||
}
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
return getIntersectionType(instantiateTypes((<IntersectionType>type).types, mapper), type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
|
||||
}
|
||||
if (type.flags & TypeFlags.Index) {
|
||||
return getIndexType(instantiateType((<IndexType>type).type, mapper));
|
||||
}
|
||||
if (type.flags & TypeFlags.IndexedAccess) {
|
||||
return getIndexedAccessType(instantiateType((<IndexedAccessType>type).objectType, mapper), instantiateType((<IndexedAccessType>type).indexType, mapper));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
@ -8538,7 +8501,8 @@ namespace ts {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
if (source.typeParameters) {
|
||||
if (source.typeParameters && source.typeParameters !== target.typeParameters) {
|
||||
target = getCanonicalSignature(target);
|
||||
source = instantiateSignatureInContextOf(source, target, /*contextualMapper*/ undefined, compareTypes);
|
||||
}
|
||||
|
||||
@ -10356,7 +10320,6 @@ namespace ts {
|
||||
function createInferenceContext(signature: Signature, flags: InferenceFlags, compareTypes?: TypeComparer, baseInferences?: InferenceInfo[]): InferenceContext {
|
||||
const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(signature.typeParameters, createInferenceInfo);
|
||||
const context = mapper as InferenceContext;
|
||||
context.mappedTypes = signature.typeParameters;
|
||||
context.signature = signature;
|
||||
context.inferences = inferences;
|
||||
context.flags = flags;
|
||||
|
||||
@ -438,8 +438,10 @@ namespace ts {
|
||||
visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression);
|
||||
}
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags) {
|
||||
visitNode(cbNode, tag);
|
||||
if ((node as JSDocTypeLiteral).jsDocPropertyTags) {
|
||||
for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags) {
|
||||
visitNode(cbNode, tag);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
@ -6667,19 +6669,18 @@ namespace ts {
|
||||
if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) {
|
||||
let child: JSDocTypeTag | JSDocPropertyTag | false;
|
||||
let jsdocTypeLiteral: JSDocTypeLiteral;
|
||||
let alreadyHasTypeTag = false;
|
||||
let childTypeTag: JSDocTypeTag;
|
||||
const start = scanner.getStartPos();
|
||||
while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.Property))) {
|
||||
if (!jsdocTypeLiteral) {
|
||||
jsdocTypeLiteral = <JSDocTypeLiteral>createNode(SyntaxKind.JSDocTypeLiteral, start);
|
||||
}
|
||||
if (child.kind === SyntaxKind.JSDocTypeTag) {
|
||||
if (alreadyHasTypeTag) {
|
||||
if (childTypeTag) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
jsdocTypeLiteral.jsDocTypeTag = child;
|
||||
alreadyHasTypeTag = true;
|
||||
childTypeTag = child;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -6693,7 +6694,9 @@ namespace ts {
|
||||
if (typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType) {
|
||||
jsdocTypeLiteral.isArrayType = true;
|
||||
}
|
||||
typedefTag.typeExpression = finishNode(jsdocTypeLiteral);
|
||||
typedefTag.typeExpression = childTypeTag && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ?
|
||||
childTypeTag.typeExpression :
|
||||
finishNode(jsdocTypeLiteral);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2150,7 +2150,6 @@ namespace ts {
|
||||
export interface JSDocTypeLiteral extends JSDocType {
|
||||
kind: SyntaxKind.JSDocTypeLiteral;
|
||||
jsDocPropertyTags?: ReadonlyArray<JSDocPropertyLikeTag>;
|
||||
jsDocTypeTag?: JSDocTypeTag;
|
||||
/** If true, then this type literal represents an *array* of its type. */
|
||||
isArrayType?: boolean;
|
||||
}
|
||||
@ -3296,13 +3295,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface MappedType extends ObjectType {
|
||||
export interface MappedType extends AnonymousType {
|
||||
declaration: MappedTypeNode;
|
||||
typeParameter?: TypeParameter;
|
||||
constraintType?: Type;
|
||||
templateType?: Type;
|
||||
modifiersType?: Type;
|
||||
mapper?: TypeMapper; // Instantiation mapper
|
||||
}
|
||||
|
||||
export interface EvolvingArrayType extends ObjectType {
|
||||
@ -3412,6 +3410,8 @@ namespace ts {
|
||||
/* @internal */
|
||||
erasedSignatureCache?: Signature; // Erased version of signature (deferred)
|
||||
/* @internal */
|
||||
canonicalSignatureCache?: Signature; // Canonical version of signature (deferred)
|
||||
/* @internal */
|
||||
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
|
||||
/* @internal */
|
||||
typePredicate?: TypePredicate;
|
||||
@ -3433,8 +3433,6 @@ namespace ts {
|
||||
/* @internal */
|
||||
export interface TypeMapper {
|
||||
(t: TypeParameter): Type;
|
||||
mappedTypes?: TypeParameter[]; // Types mapped by this mapper
|
||||
instantiations?: Type[]; // Cache of instantiations created using this type mapper.
|
||||
}
|
||||
|
||||
export const enum InferencePriority {
|
||||
|
||||
@ -235,24 +235,39 @@ namespace ts.server {
|
||||
return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}.${d.getMilliseconds()}`;
|
||||
}
|
||||
|
||||
interface QueuedOperation {
|
||||
operationId: string;
|
||||
operation: () => void;
|
||||
}
|
||||
|
||||
class NodeTypingsInstaller implements ITypingsInstaller {
|
||||
private installer: NodeChildProcess;
|
||||
private installerPidReported = false;
|
||||
private socket: NodeSocket;
|
||||
private projectService: ProjectService;
|
||||
private throttledOperations: ThrottledOperations;
|
||||
private eventSender: EventSender;
|
||||
private activeRequestCount = 0;
|
||||
private requestQueue: QueuedOperation[] = [];
|
||||
private requestMap = createMap<QueuedOperation>(); // Maps operation ID to newest requestQueue entry with that ID
|
||||
|
||||
// This number is essentially arbitrary. Processing more than one typings request
|
||||
// at a time makes sense, but having too many in the pipe results in a hang
|
||||
// (see https://github.com/nodejs/node/issues/7657).
|
||||
// It would be preferable to base our limit on the amount of space left in the
|
||||
// buffer, but we have yet to find a way to retrieve that value.
|
||||
private static readonly maxActiveRequestCount = 10;
|
||||
private static readonly requestDelayMillis = 100;
|
||||
|
||||
|
||||
constructor(
|
||||
private readonly telemetryEnabled: boolean,
|
||||
private readonly logger: server.Logger,
|
||||
host: ServerHost,
|
||||
private readonly host: ServerHost,
|
||||
eventPort: number,
|
||||
readonly globalTypingsCacheLocation: string,
|
||||
readonly typingSafeListLocation: string,
|
||||
private readonly npmLocation: string | undefined,
|
||||
private newLine: string) {
|
||||
this.throttledOperations = new ThrottledOperations(host);
|
||||
if (eventPort) {
|
||||
const s = net.connect({ port: eventPort }, () => {
|
||||
this.socket = s;
|
||||
@ -333,12 +348,26 @@ namespace ts.server {
|
||||
this.logger.info(`Scheduling throttled operation: ${JSON.stringify(request)}`);
|
||||
}
|
||||
}
|
||||
this.throttledOperations.schedule(project.getProjectName(), /*ms*/ 250, () => {
|
||||
|
||||
const operationId = project.getProjectName();
|
||||
const operation = () => {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Sending request: ${JSON.stringify(request)}`);
|
||||
}
|
||||
this.installer.send(request);
|
||||
});
|
||||
};
|
||||
const queuedRequest: QueuedOperation = { operationId, operation };
|
||||
|
||||
if (this.activeRequestCount < NodeTypingsInstaller.maxActiveRequestCount) {
|
||||
this.scheduleRequest(queuedRequest);
|
||||
}
|
||||
else {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Deferring request for: ${operationId}`);
|
||||
}
|
||||
this.requestQueue.push(queuedRequest);
|
||||
this.requestMap.set(operationId, queuedRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private handleMessage(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) {
|
||||
@ -399,11 +428,39 @@ namespace ts.server {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.activeRequestCount > 0) {
|
||||
this.activeRequestCount--;
|
||||
}
|
||||
else {
|
||||
Debug.fail("Received too many responses");
|
||||
}
|
||||
|
||||
while (this.requestQueue.length > 0) {
|
||||
const queuedRequest = this.requestQueue.shift();
|
||||
if (this.requestMap.get(queuedRequest.operationId) === queuedRequest) {
|
||||
this.requestMap.delete(queuedRequest.operationId);
|
||||
this.scheduleRequest(queuedRequest);
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Skipping defunct request for: ${queuedRequest.operationId}`);
|
||||
}
|
||||
}
|
||||
|
||||
this.projectService.updateTypingsForProject(response);
|
||||
if (response.kind === ActionSet && this.socket) {
|
||||
this.sendEvent(0, "setTypings", response);
|
||||
}
|
||||
}
|
||||
|
||||
private scheduleRequest(request: QueuedOperation) {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Scheduling request for: ${request.operationId}`);
|
||||
}
|
||||
this.activeRequestCount++;
|
||||
this.host.setTimeout(request.operation, NodeTypingsInstaller.requestDelayMillis);
|
||||
}
|
||||
}
|
||||
|
||||
class IOSession extends Session {
|
||||
|
||||
@ -179,6 +179,12 @@ namespace ts.server {
|
||||
constructor(private readonly host: ServerHost) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait `number` milliseconds and then invoke `cb`. If, while waiting, schedule
|
||||
* is called again with the same `operationId`, cancel this operation in favor
|
||||
* of the new one. (Note that the amount of time the canceled operation had been
|
||||
* waiting does not affect the amount of time that the new operation waits.)
|
||||
*/
|
||||
public schedule(operationId: string, delay: number, cb: () => void) {
|
||||
const pendingTimeout = this.pendingTimeouts.get(operationId);
|
||||
if (pendingTimeout) {
|
||||
|
||||
@ -372,8 +372,7 @@ namespace ts.SignatureHelp {
|
||||
if (isTypeParameterList) {
|
||||
isVariadic = false; // type parameter lists are not variadic
|
||||
prefixDisplayParts.push(punctuationPart(SyntaxKind.LessThanToken));
|
||||
// Use `.mapper` to ensure we get the generic type arguments even if this is an instantiated version of the signature.
|
||||
const typeParameters = candidateSignature.mapper ? candidateSignature.mapper.mappedTypes : candidateSignature.typeParameters;
|
||||
const typeParameters = (candidateSignature.target || candidateSignature).typeParameters;
|
||||
signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
|
||||
suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
|
||||
const parameterParts = mapToDisplayParts(writer =>
|
||||
|
||||
@ -34,38 +34,6 @@
|
||||
"kind": "JSDocTypeLiteral",
|
||||
"pos": 26,
|
||||
"end": 98,
|
||||
"jsDocTypeTag": {
|
||||
"kind": "JSDocTypeTag",
|
||||
"pos": 28,
|
||||
"end": 42,
|
||||
"atToken": {
|
||||
"kind": "AtToken",
|
||||
"pos": 28,
|
||||
"end": 29
|
||||
},
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 29,
|
||||
"end": 33,
|
||||
"escapedText": "type"
|
||||
},
|
||||
"typeExpression": {
|
||||
"kind": "JSDocTypeExpression",
|
||||
"pos": 34,
|
||||
"end": 42,
|
||||
"type": {
|
||||
"kind": "TypeReference",
|
||||
"pos": 35,
|
||||
"end": 41,
|
||||
"typeName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 35,
|
||||
"end": 41,
|
||||
"escapedText": "Object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"jsDocPropertyTags": [
|
||||
{
|
||||
"kind": "JSDocPropertyTag",
|
||||
|
||||
@ -22,8 +22,6 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/functionConstrain
|
||||
Type 'void' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/typeParameters/typeArgumentLists/functionConstraintSatisfaction2.ts(38,10): error TS2345: Argument of type 'U' is not assignable to parameter of type '(x: string) => string'.
|
||||
Type 'T' is not assignable to type '(x: string) => string'.
|
||||
Type '() => void' is not assignable to type '(x: string) => string'.
|
||||
Type 'void' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/typeParameters/typeArgumentLists/functionConstraintSatisfaction2.ts (13 errors) ====
|
||||
@ -102,7 +100,5 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/functionConstrain
|
||||
~
|
||||
!!! error TS2345: Argument of type 'U' is not assignable to parameter of type '(x: string) => string'.
|
||||
!!! error TS2345: Type 'T' is not assignable to type '(x: string) => string'.
|
||||
!!! error TS2345: Type '() => void' is not assignable to type '(x: string) => string'.
|
||||
!!! error TS2345: Type 'void' is not assignable to type 'string'.
|
||||
}
|
||||
|
||||
10
tests/baselines/reference/jsdocTwoLineTypedef.js
Normal file
10
tests/baselines/reference/jsdocTwoLineTypedef.js
Normal file
@ -0,0 +1,10 @@
|
||||
//// [jsdocTwoLineTypedef.ts]
|
||||
// Regression from #18301
|
||||
/**
|
||||
* @typedef LoadCallback
|
||||
* @type {function}
|
||||
*/
|
||||
type LoadCallback = void;
|
||||
|
||||
|
||||
//// [jsdocTwoLineTypedef.js]
|
||||
9
tests/baselines/reference/jsdocTwoLineTypedef.symbols
Normal file
9
tests/baselines/reference/jsdocTwoLineTypedef.symbols
Normal file
@ -0,0 +1,9 @@
|
||||
=== tests/cases/conformance/jsdoc/jsdocTwoLineTypedef.ts ===
|
||||
// Regression from #18301
|
||||
/**
|
||||
* @typedef LoadCallback
|
||||
* @type {function}
|
||||
*/
|
||||
type LoadCallback = void;
|
||||
>LoadCallback : Symbol(LoadCallback, Decl(jsdocTwoLineTypedef.ts, 0, 0))
|
||||
|
||||
9
tests/baselines/reference/jsdocTwoLineTypedef.types
Normal file
9
tests/baselines/reference/jsdocTwoLineTypedef.types
Normal file
@ -0,0 +1,9 @@
|
||||
=== tests/cases/conformance/jsdoc/jsdocTwoLineTypedef.ts ===
|
||||
// Regression from #18301
|
||||
/**
|
||||
* @typedef LoadCallback
|
||||
* @type {function}
|
||||
*/
|
||||
type LoadCallback = void;
|
||||
>LoadCallback : void
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
tests/cases/compiler/limitDeepInstantiations.ts(3,35): error TS2550: Generic type instantiation is excessively deep and possibly infinite.
|
||||
tests/cases/compiler/limitDeepInstantiations.ts(3,35): error TS2502: '"true"' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/compiler/limitDeepInstantiations.ts(5,13): error TS2344: Type '"false"' does not satisfy the constraint '"true"'.
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ tests/cases/compiler/limitDeepInstantiations.ts(5,13): error TS2344: Type '"fals
|
||||
|
||||
type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2550: Generic type instantiation is excessively deep and possibly infinite.
|
||||
!!! error TS2502: '"true"' is referenced directly or indirectly in its own type annotation.
|
||||
let f1: Foo<"true", {}>;
|
||||
let f2: Foo<"false", {}>;
|
||||
~~~~~~~
|
||||
|
||||
@ -45,7 +45,6 @@ tests/cases/compiler/promisePermutations.ts(134,19): error TS2345: Argument of t
|
||||
tests/cases/compiler/promisePermutations.ts(137,33): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
|
||||
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
|
||||
tests/cases/compiler/promisePermutations.ts(144,35): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
|
||||
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
|
||||
tests/cases/compiler/promisePermutations.ts(152,36): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
|
||||
Type 'IPromise<string>' is not assignable to type 'Promise<number>'.
|
||||
Types of property 'then' are incompatible.
|
||||
@ -290,7 +289,6 @@ tests/cases/compiler/promisePermutations.ts(160,21): error TS2345: Argument of t
|
||||
var r10d = r10.then(testFunction, sIPromise, nIPromise); // ok
|
||||
~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
|
||||
!!! error TS2345: Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
|
||||
var r10e = r10.then(testFunction, nIPromise, sIPromise).then(sIPromise, sIPromise, sIPromise); // ok
|
||||
var s10 = testFunction10P(x => x);
|
||||
var s10a = s10.then(testFunction10, testFunction10, testFunction10); // ok
|
||||
|
||||
@ -45,7 +45,6 @@ tests/cases/compiler/promisePermutations2.ts(133,19): error TS2345: Argument of
|
||||
tests/cases/compiler/promisePermutations2.ts(136,33): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
|
||||
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
|
||||
tests/cases/compiler/promisePermutations2.ts(143,35): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
|
||||
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
|
||||
tests/cases/compiler/promisePermutations2.ts(151,36): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
|
||||
Type 'IPromise<string>' is not assignable to type 'Promise<number>'.
|
||||
Types of property 'then' are incompatible.
|
||||
@ -289,7 +288,6 @@ tests/cases/compiler/promisePermutations2.ts(159,21): error TS2345: Argument of
|
||||
var r10d = r10.then(testFunction, sIPromise, nIPromise); // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
|
||||
!!! error TS2345: Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
|
||||
var r10e = r10.then(testFunction, nIPromise, sIPromise).then(sIPromise, sIPromise, sIPromise); // ok
|
||||
var s10 = testFunction10P(x => x);
|
||||
var s10a = s10.then(testFunction10, testFunction10, testFunction10); // ok
|
||||
|
||||
@ -48,7 +48,6 @@ tests/cases/compiler/promisePermutations3.ts(133,19): error TS2345: Argument of
|
||||
tests/cases/compiler/promisePermutations3.ts(136,33): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
|
||||
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
|
||||
tests/cases/compiler/promisePermutations3.ts(143,35): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
|
||||
Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
|
||||
tests/cases/compiler/promisePermutations3.ts(151,36): error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
|
||||
Type 'IPromise<string>' is not assignable to type 'Promise<number>'.
|
||||
Types of property 'then' are incompatible.
|
||||
@ -301,7 +300,6 @@ tests/cases/compiler/promisePermutations3.ts(165,21): error TS2345: Argument of
|
||||
var r10d = r10.then(testFunction, sIPromise, nIPromise); // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => IPromise<number>'.
|
||||
!!! error TS2345: Type 'IPromise<string>' is not assignable to type 'IPromise<number>'.
|
||||
var r10e = r10.then(testFunction, nIPromise, sIPromise).then(sIPromise, sIPromise, sIPromise); // ok
|
||||
var s10 = testFunction10P(x => x);
|
||||
var s10a = s10.then(testFunction10, testFunction10, testFunction10); // ok
|
||||
|
||||
6
tests/cases/conformance/jsdoc/jsdocTwoLineTypedef.ts
Normal file
6
tests/cases/conformance/jsdoc/jsdocTwoLineTypedef.ts
Normal file
@ -0,0 +1,6 @@
|
||||
// Regression from #18301
|
||||
/**
|
||||
* @typedef LoadCallback
|
||||
* @type {function}
|
||||
*/
|
||||
type LoadCallback = void;
|
||||
Loading…
x
Reference in New Issue
Block a user