mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Generate names for type parameter declarations in inferred types (#23902)
* Generate names for type parameter declarations in inferred types * Fix lint * Merge functions, make overload private * Handle some edge cases better (nodes in differing files than current emit) * Account for transformed nodes
This commit is contained in:
1 parent
1b796ed04d
commit
6149b41469
12 files changed
+192
-27
No files matched your search
+24
-4
@@ -2746,7 +2746,7 @@ namespace ts {
|
||||
* @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible
|
||||
*/
|
||||
function isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean): SymbolAccessibilityResult {
|
||||
if (symbol && enclosingDeclaration && !(symbol.flags & SymbolFlags.TypeParameter)) {
|
||||
if (symbol && enclosingDeclaration) {
|
||||
const initialSymbol = symbol;
|
||||
let meaningToLook = meaning;
|
||||
while (symbol) {
|
||||
@@ -3118,7 +3118,15 @@ namespace ts {
|
||||
}
|
||||
if (type.flags & TypeFlags.TypeParameter || objectFlags & ObjectFlags.ClassOrInterface) {
|
||||
if (type.flags & TypeFlags.TypeParameter && contains(context.inferTypeParameters, type)) {
|
||||
return createInferTypeNode(createTypeParameterDeclaration(getNameOfSymbolAsWritten(type.symbol)));
|
||||
return createInferTypeNode(typeParameterToDeclarationWithConstraint(type as TypeParameter, context, /*constraintNode*/ undefined));
|
||||
}
|
||||
if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams &&
|
||||
type.flags & TypeFlags.TypeParameter &&
|
||||
length(type.symbol.declarations) &&
|
||||
isTypeParameterDeclaration(type.symbol.declarations[0]) &&
|
||||
typeParameterShadowsNameInScope(type, context) &&
|
||||
!isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration)) {
|
||||
return createTypeReferenceNode(getGeneratedNameForNode((type.symbol.declarations[0] as TypeParameterDeclaration).name, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes), /*typeArguments*/ undefined);
|
||||
}
|
||||
const name = type.symbol ? symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ false) : createIdentifier("?");
|
||||
// Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter.
|
||||
@@ -3563,10 +3571,21 @@ namespace ts {
|
||||
return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode, typeArguments);
|
||||
}
|
||||
|
||||
function typeParameterToDeclarationWithConstraint(type: TypeParameter, context: NodeBuilderContext, constraintNode: TypeNode): TypeParameterDeclaration {
|
||||
function typeParameterShadowsNameInScope(type: TypeParameter, context: NodeBuilderContext) {
|
||||
return !!resolveName(context.enclosingDeclaration, type.symbol.escapedName, SymbolFlags.Type, /*nameNotFoundArg*/ undefined, type.symbol.escapedName, /*isUse*/ false);
|
||||
}
|
||||
|
||||
function typeParameterToDeclarationWithConstraint(type: TypeParameter, context: NodeBuilderContext, constraintNode: TypeNode | undefined): TypeParameterDeclaration {
|
||||
const savedContextFlags = context.flags;
|
||||
context.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic
|
||||
const name = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true);
|
||||
const shouldUseGeneratedName =
|
||||
context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams &&
|
||||
type.symbol.declarations[0] &&
|
||||
isTypeParameterDeclaration(type.symbol.declarations[0]) &&
|
||||
typeParameterShadowsNameInScope(type, context);
|
||||
const name = shouldUseGeneratedName
|
||||
? getGeneratedNameForNode((type.symbol.declarations[0] as TypeParameterDeclaration).name, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes)
|
||||
: symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true);
|
||||
const defaultParameter = getDefaultFromTypeParameter(type);
|
||||
const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context);
|
||||
context.flags = savedContextFlags;
|
||||
@@ -3799,6 +3818,7 @@ namespace ts {
|
||||
if (index === 0) {
|
||||
context.flags ^= NodeBuilderFlags.InInitialEntityName;
|
||||
}
|
||||
|
||||
const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping);
|
||||
identifier.symbol = symbol;
|
||||
|
||||
|
||||
+38
-12
@@ -1132,6 +1132,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitMethodSignature(node: MethodSignature) {
|
||||
pushNameGenerationScope(node);
|
||||
emitDecorators(node, node.decorators);
|
||||
emitModifiers(node, node.modifiers);
|
||||
emit(node.name);
|
||||
@@ -1140,6 +1141,7 @@ namespace ts {
|
||||
emitParameters(node, node.parameters);
|
||||
emitTypeAnnotation(node.type);
|
||||
writeSemicolon();
|
||||
popNameGenerationScope(node);
|
||||
}
|
||||
|
||||
function emitMethodDeclaration(node: MethodDeclaration) {
|
||||
@@ -1167,15 +1169,18 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitCallSignature(node: CallSignatureDeclaration) {
|
||||
pushNameGenerationScope(node);
|
||||
emitDecorators(node, node.decorators);
|
||||
emitModifiers(node, node.modifiers);
|
||||
emitTypeParameters(node, node.typeParameters);
|
||||
emitParameters(node, node.parameters);
|
||||
emitTypeAnnotation(node.type);
|
||||
writeSemicolon();
|
||||
popNameGenerationScope(node);
|
||||
}
|
||||
|
||||
function emitConstructSignature(node: ConstructSignatureDeclaration) {
|
||||
pushNameGenerationScope(node);
|
||||
emitDecorators(node, node.decorators);
|
||||
emitModifiers(node, node.modifiers);
|
||||
writeKeyword("new");
|
||||
@@ -1184,6 +1189,7 @@ namespace ts {
|
||||
emitParameters(node, node.parameters);
|
||||
emitTypeAnnotation(node.type);
|
||||
writeSemicolon();
|
||||
popNameGenerationScope(node);
|
||||
}
|
||||
|
||||
function emitIndexSignature(node: IndexSignatureDeclaration) {
|
||||
@@ -1216,12 +1222,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitFunctionType(node: FunctionTypeNode) {
|
||||
pushNameGenerationScope(node);
|
||||
emitTypeParameters(node, node.typeParameters);
|
||||
emitParametersForArrow(node, node.parameters);
|
||||
writeSpace();
|
||||
writePunctuation("=>");
|
||||
writeSpace();
|
||||
emit(node.type);
|
||||
popNameGenerationScope(node);
|
||||
}
|
||||
|
||||
function emitJSDocFunctionType(node: JSDocFunctionType) {
|
||||
@@ -1248,6 +1256,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitConstructorType(node: ConstructorTypeNode) {
|
||||
pushNameGenerationScope(node);
|
||||
writeKeyword("new");
|
||||
writeSpace();
|
||||
emitTypeParameters(node, node.typeParameters);
|
||||
@@ -1256,6 +1265,7 @@ namespace ts {
|
||||
writePunctuation("=>");
|
||||
writeSpace();
|
||||
emit(node.type);
|
||||
popNameGenerationScope(node);
|
||||
}
|
||||
|
||||
function emitTypeQuery(node: TypeQueryNode) {
|
||||
@@ -3241,7 +3251,7 @@ namespace ts {
|
||||
if (isGeneratedIdentifier(node)) {
|
||||
return generateName(node);
|
||||
}
|
||||
else if (isIdentifier(node) && (nodeIsSynthesized(node) || !node.parent)) {
|
||||
else if (isIdentifier(node) && (nodeIsSynthesized(node) || !node.parent || !currentSourceFile || (node.parent && currentSourceFile && getSourceFileOfNode(node) !== getOriginalNode(currentSourceFile)))) {
|
||||
return idText(node);
|
||||
}
|
||||
else if (node.kind === SyntaxKind.StringLiteral && (<StringLiteral>node).textSourceNode) {
|
||||
@@ -3415,7 +3425,7 @@ namespace ts {
|
||||
if ((name.autoGenerateFlags & GeneratedIdentifierFlags.KindMask) === GeneratedIdentifierFlags.Node) {
|
||||
// Node names generate unique names based on their original node
|
||||
// and are cached based on that node's id.
|
||||
return generateNameCached(getNodeForGeneratedName(name));
|
||||
return generateNameCached(getNodeForGeneratedName(name), name.autoGenerateFlags);
|
||||
}
|
||||
else {
|
||||
// Auto, Loop, and Unique names are cached based on their unique
|
||||
@@ -3425,9 +3435,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function generateNameCached(node: Node) {
|
||||
function generateNameCached(node: Node, flags?: GeneratedIdentifierFlags) {
|
||||
const nodeId = getNodeId(node);
|
||||
return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = generateNameForNode(node));
|
||||
return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = generateNameForNode(node, flags));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3444,7 +3454,7 @@ namespace ts {
|
||||
* Returns a value indicating whether a name is unique globally or within the current file.
|
||||
*/
|
||||
function isFileLevelUniqueName(name: string) {
|
||||
return ts.isFileLevelUniqueName(currentSourceFile, name, hasGlobalName);
|
||||
return currentSourceFile ? ts.isFileLevelUniqueName(currentSourceFile, name, hasGlobalName) : true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3504,10 +3514,15 @@ namespace ts {
|
||||
* makeUniqueName are guaranteed to never conflict.
|
||||
* If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1'
|
||||
*/
|
||||
function makeUniqueName(baseName: string, checkFn: (name: string) => boolean = isUniqueName, optimistic?: boolean): string {
|
||||
function makeUniqueName(baseName: string, checkFn: (name: string) => boolean = isUniqueName, optimistic?: boolean, scoped?: boolean): string {
|
||||
if (optimistic) {
|
||||
if (checkFn(baseName)) {
|
||||
generatedNames.set(baseName, true);
|
||||
if (scoped) {
|
||||
reserveNameInNestedScopes(baseName);
|
||||
}
|
||||
else {
|
||||
generatedNames.set(baseName, true);
|
||||
}
|
||||
return baseName;
|
||||
}
|
||||
}
|
||||
@@ -3519,7 +3534,12 @@ namespace ts {
|
||||
while (true) {
|
||||
const generatedName = baseName + i;
|
||||
if (checkFn(generatedName)) {
|
||||
generatedNames.set(generatedName, true);
|
||||
if (scoped) {
|
||||
reserveNameInNestedScopes(generatedName);
|
||||
}
|
||||
else {
|
||||
generatedNames.set(generatedName, true);
|
||||
}
|
||||
return generatedName;
|
||||
}
|
||||
i++;
|
||||
@@ -3573,10 +3593,15 @@ namespace ts {
|
||||
/**
|
||||
* Generates a unique name from a node.
|
||||
*/
|
||||
function generateNameForNode(node: Node): string {
|
||||
function generateNameForNode(node: Node, flags?: GeneratedIdentifierFlags): string {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return makeUniqueName(getTextOfNode(node));
|
||||
return makeUniqueName(
|
||||
getTextOfNode(node),
|
||||
isUniqueName,
|
||||
!!(flags & GeneratedIdentifierFlags.Optimistic),
|
||||
!!(flags & GeneratedIdentifierFlags.ReservedInNestedScopes)
|
||||
);
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
return generateNameForModuleOrEnum(<ModuleDeclaration | EnumDeclaration>node);
|
||||
@@ -3611,7 +3636,8 @@ namespace ts {
|
||||
return makeUniqueName(
|
||||
idText(name),
|
||||
(name.autoGenerateFlags & GeneratedIdentifierFlags.FileLevel) ? isFileLevelUniqueName : isUniqueName,
|
||||
!!(name.autoGenerateFlags & GeneratedIdentifierFlags.Optimistic)
|
||||
!!(name.autoGenerateFlags & GeneratedIdentifierFlags.Optimistic),
|
||||
!!(name.autoGenerateFlags & GeneratedIdentifierFlags.ReservedInNestedScopes)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3631,7 +3657,7 @@ namespace ts {
|
||||
// if "node" is a different generated name (having a different
|
||||
// "autoGenerateId"), use it and stop traversing.
|
||||
if (isIdentifier(node)
|
||||
&& node.autoGenerateFlags === GeneratedIdentifierFlags.Node
|
||||
&& !!(node.autoGenerateFlags & GeneratedIdentifierFlags.Node)
|
||||
&& node.autoGenerateId !== autoGenerateId) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -192,9 +192,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Create a unique name generated for a node. */
|
||||
export function getGeneratedNameForNode(node: Node): Identifier {
|
||||
const name = createIdentifier("");
|
||||
name.autoGenerateFlags = GeneratedIdentifierFlags.Node;
|
||||
export function getGeneratedNameForNode(node: Node): Identifier;
|
||||
/* @internal */ export function getGeneratedNameForNode(node: Node, flags: GeneratedIdentifierFlags): Identifier; // tslint:disable-line unified-signatures
|
||||
export function getGeneratedNameForNode(node: Node, flags?: GeneratedIdentifierFlags): Identifier {
|
||||
const name = createIdentifier(isIdentifier(node) ? idText(node) : "");
|
||||
name.autoGenerateFlags = GeneratedIdentifierFlags.Node | flags;
|
||||
name.autoGenerateId = nextAutoGenerateId;
|
||||
name.original = node;
|
||||
nextAutoGenerateId++;
|
||||
@@ -4246,6 +4248,7 @@ namespace ts {
|
||||
switch (member.kind) {
|
||||
case SyntaxKind.TypeQuery:
|
||||
case SyntaxKind.TypeOperator:
|
||||
case SyntaxKind.InferType:
|
||||
return createParenthesizedType(member);
|
||||
}
|
||||
return parenthesizeElementTypeMember(member);
|
||||
|
||||
@@ -9,7 +9,13 @@ namespace ts {
|
||||
return result.diagnostics;
|
||||
}
|
||||
|
||||
const declarationEmitNodeBuilderFlags = NodeBuilderFlags.MultilineObjectLiterals | TypeFormatFlags.WriteClassExpressionAsTypeLiteral | NodeBuilderFlags.UseTypeOfFunction | NodeBuilderFlags.UseStructuralFallback | NodeBuilderFlags.AllowEmptyTuple;
|
||||
const declarationEmitNodeBuilderFlags =
|
||||
NodeBuilderFlags.MultilineObjectLiterals |
|
||||
TypeFormatFlags.WriteClassExpressionAsTypeLiteral |
|
||||
NodeBuilderFlags.UseTypeOfFunction |
|
||||
NodeBuilderFlags.UseStructuralFallback |
|
||||
NodeBuilderFlags.AllowEmptyTuple |
|
||||
NodeBuilderFlags.GenerateNamesForShadowedTypeParams;
|
||||
|
||||
/**
|
||||
* Transforms a ts file into a .d.ts file
|
||||
@@ -95,6 +101,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
|
||||
if (symbol.flags & SymbolFlags.TypeParameter) return;
|
||||
handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true));
|
||||
recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning));
|
||||
}
|
||||
|
||||
@@ -3074,7 +3074,7 @@ namespace ts {
|
||||
// Options
|
||||
NoTruncation = 1 << 0, // Don't truncate result
|
||||
WriteArrayAsGenericType = 1 << 1, // Write Array<T> instead T[]
|
||||
// empty space
|
||||
GenerateNamesForShadowedTypeParams = 1 << 2, // When a type parameter T is shadowing another T, generate a name for it so it can still be referenced
|
||||
UseStructuralFallback = 1 << 3, // When an alias cannot be named by its symbol, rather than report an error, fallback to a structural printout if possible
|
||||
// empty space
|
||||
WriteTypeArgumentsOfSignature = 1 << 5, // Write the type arguments instead of type parameters of the signature
|
||||
|
||||
@@ -1883,6 +1883,7 @@ declare namespace ts {
|
||||
None = 0,
|
||||
NoTruncation = 1,
|
||||
WriteArrayAsGenericType = 2,
|
||||
GenerateNamesForShadowedTypeParams = 4,
|
||||
UseStructuralFallback = 8,
|
||||
WriteTypeArgumentsOfSignature = 32,
|
||||
UseFullyQualifiedType = 64,
|
||||
|
||||
@@ -1883,6 +1883,7 @@ declare namespace ts {
|
||||
None = 0,
|
||||
NoTruncation = 1,
|
||||
WriteArrayAsGenericType = 2,
|
||||
GenerateNamesForShadowedTypeParams = 4,
|
||||
UseStructuralFallback = 8,
|
||||
WriteTypeArgumentsOfSignature = 32,
|
||||
UseFullyQualifiedType = 64,
|
||||
|
||||
@@ -927,9 +927,9 @@ type T52 = IsNever<any>; // false
|
||||
>IsNever : IsNever<T>
|
||||
|
||||
function f22<T>(x: T extends (infer U)[] ? U[] : never) {
|
||||
>f22 : <T>(x: T extends infer U[] ? U[] : never) => void
|
||||
>f22 : <T>(x: T extends (infer U)[] ? U[] : never) => void
|
||||
>T : T
|
||||
>x : T extends infer U[] ? U[] : never
|
||||
>x : T extends (infer U)[] ? U[] : never
|
||||
>T : T
|
||||
>U : U
|
||||
>U : U
|
||||
@@ -937,14 +937,14 @@ function f22<T>(x: T extends (infer U)[] ? U[] : never) {
|
||||
let e = x[0]; // {}
|
||||
>e : {}
|
||||
>x[0] : {}
|
||||
>x : T extends infer U[] ? U[] : never
|
||||
>x : T extends (infer U)[] ? U[] : never
|
||||
>0 : 0
|
||||
}
|
||||
|
||||
function f23<T extends string[]>(x: T extends (infer U)[] ? U[] : never) {
|
||||
>f23 : <T extends string[]>(x: T extends infer U[] ? U[] : never) => void
|
||||
>f23 : <T extends string[]>(x: T extends (infer U)[] ? U[] : never) => void
|
||||
>T : T
|
||||
>x : T extends infer U[] ? U[] : never
|
||||
>x : T extends (infer U)[] ? U[] : never
|
||||
>T : T
|
||||
>U : U
|
||||
>U : U
|
||||
@@ -952,7 +952,7 @@ function f23<T extends string[]>(x: T extends (infer U)[] ? U[] : never) {
|
||||
let e = x[0]; // string
|
||||
>e : string
|
||||
>x[0] : string
|
||||
>x : T extends infer U[] ? U[] : never
|
||||
>x : T extends (infer U)[] ? U[] : never
|
||||
>0 : 0
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
//// [declarationEmitNestedGenerics.ts]
|
||||
function f<T>(p: T) {
|
||||
let g: <T>(x: T) => typeof p = null as any;
|
||||
return g;
|
||||
}
|
||||
|
||||
function g<T>(x: T) {
|
||||
let y: typeof x extends (infer T)[] ? T : typeof x = null as any;
|
||||
return y;
|
||||
}
|
||||
|
||||
//// [declarationEmitNestedGenerics.js]
|
||||
function f(p) {
|
||||
var g = null;
|
||||
return g;
|
||||
}
|
||||
function g(x) {
|
||||
var y = null;
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
//// [declarationEmitNestedGenerics.d.ts]
|
||||
declare function f<T>(p: T): <T_1>(x: T_1) => T;
|
||||
declare function g<T>(x: T): T extends (infer T_1)[] ? T_1 : T;
|
||||
@@ -0,0 +1,34 @@
|
||||
=== tests/cases/compiler/declarationEmitNestedGenerics.ts ===
|
||||
function f<T>(p: T) {
|
||||
>f : Symbol(f, Decl(declarationEmitNestedGenerics.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(declarationEmitNestedGenerics.ts, 0, 11))
|
||||
>p : Symbol(p, Decl(declarationEmitNestedGenerics.ts, 0, 14))
|
||||
>T : Symbol(T, Decl(declarationEmitNestedGenerics.ts, 0, 11))
|
||||
|
||||
let g: <T>(x: T) => typeof p = null as any;
|
||||
>g : Symbol(g, Decl(declarationEmitNestedGenerics.ts, 1, 7))
|
||||
>T : Symbol(T, Decl(declarationEmitNestedGenerics.ts, 1, 12))
|
||||
>x : Symbol(x, Decl(declarationEmitNestedGenerics.ts, 1, 15))
|
||||
>T : Symbol(T, Decl(declarationEmitNestedGenerics.ts, 1, 12))
|
||||
>p : Symbol(p, Decl(declarationEmitNestedGenerics.ts, 0, 14))
|
||||
|
||||
return g;
|
||||
>g : Symbol(g, Decl(declarationEmitNestedGenerics.ts, 1, 7))
|
||||
}
|
||||
|
||||
function g<T>(x: T) {
|
||||
>g : Symbol(g, Decl(declarationEmitNestedGenerics.ts, 3, 1))
|
||||
>T : Symbol(T, Decl(declarationEmitNestedGenerics.ts, 5, 11))
|
||||
>x : Symbol(x, Decl(declarationEmitNestedGenerics.ts, 5, 14))
|
||||
>T : Symbol(T, Decl(declarationEmitNestedGenerics.ts, 5, 11))
|
||||
|
||||
let y: typeof x extends (infer T)[] ? T : typeof x = null as any;
|
||||
>y : Symbol(y, Decl(declarationEmitNestedGenerics.ts, 6, 7))
|
||||
>x : Symbol(x, Decl(declarationEmitNestedGenerics.ts, 5, 14))
|
||||
>T : Symbol(T, Decl(declarationEmitNestedGenerics.ts, 6, 34))
|
||||
>T : Symbol(T, Decl(declarationEmitNestedGenerics.ts, 6, 34))
|
||||
>x : Symbol(x, Decl(declarationEmitNestedGenerics.ts, 5, 14))
|
||||
|
||||
return y;
|
||||
>y : Symbol(y, Decl(declarationEmitNestedGenerics.ts, 6, 7))
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
=== tests/cases/compiler/declarationEmitNestedGenerics.ts ===
|
||||
function f<T>(p: T) {
|
||||
>f : <T>(p: T) => <T>(x: T) => T
|
||||
>T : T
|
||||
>p : T
|
||||
>T : T
|
||||
|
||||
let g: <T>(x: T) => typeof p = null as any;
|
||||
>g : <T>(x: T) => T
|
||||
>T : T
|
||||
>x : T
|
||||
>T : T
|
||||
>p : T
|
||||
>null as any : any
|
||||
>null : null
|
||||
|
||||
return g;
|
||||
>g : <T>(x: T) => T
|
||||
}
|
||||
|
||||
function g<T>(x: T) {
|
||||
>g : <T>(x: T) => T extends (infer T)[] ? T : T
|
||||
>T : T
|
||||
>x : T
|
||||
>T : T
|
||||
|
||||
let y: typeof x extends (infer T)[] ? T : typeof x = null as any;
|
||||
>y : T extends (infer T)[] ? T : T
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
>x : T
|
||||
>null as any : any
|
||||
>null : null
|
||||
|
||||
return y;
|
||||
>y : T extends (infer T)[] ? T : T
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// @declaration: true
|
||||
function f<T>(p: T) {
|
||||
let g: <T>(x: T) => typeof p = null as any;
|
||||
return g;
|
||||
}
|
||||
|
||||
function g<T>(x: T) {
|
||||
let y: typeof x extends (infer T)[] ? T : typeof x = null as any;
|
||||
return y;
|
||||
}
|
||||
Reference in new issue
Block a user