mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Merge pull request #11931 from Microsoft/release-2.1_fixDeclarationEmitTypeAlaisWithTypeParam
[Release-2.1] Fix declaration emit when using type parameters
This commit is contained in:
commit
ad9c148168
@ -2199,15 +2199,32 @@ namespace ts {
|
||||
// The specified symbol flags need to be reinterpreted as type flags
|
||||
buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
|
||||
}
|
||||
else if (!(flags & TypeFormatFlags.InTypeAlias) && ((getObjectFlags(type) & ObjectFlags.Anonymous && !(<AnonymousType>type).target) || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol &&
|
||||
else if (!(flags & TypeFormatFlags.InTypeAlias) &&
|
||||
(getObjectFlags(type) & ObjectFlags.Anonymous && !(<AnonymousType>type).target || type.flags & TypeFlags.UnionOrIntersection) &&
|
||||
type.aliasSymbol &&
|
||||
isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
|
||||
// We emit inferred type as type-alias at the current localtion if all the following is true
|
||||
// the input type is has alias symbol that is accessible
|
||||
// the input type is a union, intersection or anonymous type that is fully instantiated (if not we want to keep dive into)
|
||||
// e.g.: export type Bar<X, Y> = () => [X, Y];
|
||||
// export type Foo<Y> = Bar<any, Y>;
|
||||
// export const y = (x: Foo<string>) => 1 // we want to emit as ...x: () => [any, string])
|
||||
const typeArguments = type.aliasTypeArguments;
|
||||
// We emit inferred type as type-alias if type is not in type-alias declaration, existed accessible alias-symbol, type is anonymous or union or intersection.
|
||||
// However, if the type is an anonymous type with type arguments, we need to perform additional check.
|
||||
// 1) No type arguments, just emit type-alias as is
|
||||
// 2) Existed type arguments, check if the type arguments full fill all type parameters of the alias-symbol by
|
||||
// checking whether the target's aliasTypeArguments has the same size as type's aliasTypeArguments:
|
||||
// i.e
|
||||
// type Foo<T> = {
|
||||
// foo<U>(): Foo<U>
|
||||
// };
|
||||
// function foo() {
|
||||
// return {} as Foo<number>;
|
||||
// }
|
||||
// Should be emitted as
|
||||
// declare type Foo<T> = {
|
||||
// foo<U>(): Foo<U>;
|
||||
// };
|
||||
// declare function foo(): Foo<number>;
|
||||
// Otherwise type-alias is point to another generic type-alias then don't write it using alias symbol
|
||||
// export type Bar<X, Y> = () => [X, Y];
|
||||
// export type Foo<Y> = Bar<any, Y>;
|
||||
// export const y = (x: Foo<string>) => 1 // this should be emit as "export declare const y: (x: () => [any, string]) => number;"
|
||||
const typeArguments = (<AnonymousType>type).aliasTypeArguments;
|
||||
writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags);
|
||||
}
|
||||
else if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
@ -2330,7 +2347,9 @@ namespace ts {
|
||||
else if (contains(symbolStack, symbol)) {
|
||||
// If type is an anonymous type literal in a type alias declaration, use type alias name
|
||||
const typeAlias = getTypeAliasForTypeLiteral(type);
|
||||
if (typeAlias) {
|
||||
// We only want to use type-alias here if the typeAlias is not a generic one. (i.e it doesn't have a target type)
|
||||
// If it is a generic type-alias just write out "any"
|
||||
if (typeAlias && !(<AnonymousType>type).target) {
|
||||
// The specified symbol flags need to be reinterpreted as type flags
|
||||
buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags);
|
||||
}
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
//// [declarationEmitTypeAliasWithTypeParameters2.ts]
|
||||
|
||||
export type Bar<X, Y, Z> = () => [X, Y, Z];
|
||||
export type Baz<M, N> = Bar<M, string, N>;
|
||||
export type Baa<Y> = Baz<boolean, Y>;
|
||||
export const y = (x: Baa<number>) => 1
|
||||
|
||||
//// [declarationEmitTypeAliasWithTypeParameters2.js]
|
||||
"use strict";
|
||||
exports.y = function (x) { return 1; };
|
||||
|
||||
|
||||
//// [declarationEmitTypeAliasWithTypeParameters2.d.ts]
|
||||
export declare type Bar<X, Y, Z> = () => [X, Y, Z];
|
||||
export declare type Baz<M, N> = Bar<M, string, N>;
|
||||
export declare type Baa<Y> = Baz<boolean, Y>;
|
||||
export declare const y: (x: () => [boolean, string, number]) => number;
|
||||
@ -0,0 +1,30 @@
|
||||
=== tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters2.ts ===
|
||||
|
||||
export type Bar<X, Y, Z> = () => [X, Y, Z];
|
||||
>Bar : Symbol(Bar, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 0, 0))
|
||||
>X : Symbol(X, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 1, 16))
|
||||
>Y : Symbol(Y, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 1, 18))
|
||||
>Z : Symbol(Z, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 1, 21))
|
||||
>X : Symbol(X, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 1, 16))
|
||||
>Y : Symbol(Y, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 1, 18))
|
||||
>Z : Symbol(Z, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 1, 21))
|
||||
|
||||
export type Baz<M, N> = Bar<M, string, N>;
|
||||
>Baz : Symbol(Baz, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 1, 43))
|
||||
>M : Symbol(M, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 2, 16))
|
||||
>N : Symbol(N, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 2, 18))
|
||||
>Bar : Symbol(Bar, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 0, 0))
|
||||
>M : Symbol(M, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 2, 16))
|
||||
>N : Symbol(N, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 2, 18))
|
||||
|
||||
export type Baa<Y> = Baz<boolean, Y>;
|
||||
>Baa : Symbol(Baa, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 2, 42))
|
||||
>Y : Symbol(Y, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 3, 16))
|
||||
>Baz : Symbol(Baz, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 1, 43))
|
||||
>Y : Symbol(Y, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 3, 16))
|
||||
|
||||
export const y = (x: Baa<number>) => 1
|
||||
>y : Symbol(y, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 4, 12))
|
||||
>x : Symbol(x, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 4, 18))
|
||||
>Baa : Symbol(Baa, Decl(declarationEmitTypeAliasWithTypeParameters2.ts, 2, 42))
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
=== tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters2.ts ===
|
||||
|
||||
export type Bar<X, Y, Z> = () => [X, Y, Z];
|
||||
>Bar : Bar<X, Y, Z>
|
||||
>X : X
|
||||
>Y : Y
|
||||
>Z : Z
|
||||
>X : X
|
||||
>Y : Y
|
||||
>Z : Z
|
||||
|
||||
export type Baz<M, N> = Bar<M, string, N>;
|
||||
>Baz : () => [M, string, N]
|
||||
>M : M
|
||||
>N : N
|
||||
>Bar : Bar<X, Y, Z>
|
||||
>M : M
|
||||
>N : N
|
||||
|
||||
export type Baa<Y> = Baz<boolean, Y>;
|
||||
>Baa : () => [boolean, string, Y]
|
||||
>Y : Y
|
||||
>Baz : () => [M, string, N]
|
||||
>Y : Y
|
||||
|
||||
export const y = (x: Baa<number>) => 1
|
||||
>y : (x: () => [boolean, string, number]) => number
|
||||
>(x: Baa<number>) => 1 : (x: () => [boolean, string, number]) => number
|
||||
>x : () => [boolean, string, number]
|
||||
>Baa : () => [boolean, string, Y]
|
||||
>1 : 1
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
//// [declarationEmitTypeAliasWithTypeParameters3.ts]
|
||||
|
||||
type Foo<T> = {
|
||||
foo<U>(): Foo<U>
|
||||
};
|
||||
function bar() {
|
||||
return {} as Foo<number>;
|
||||
}
|
||||
|
||||
|
||||
//// [declarationEmitTypeAliasWithTypeParameters3.js]
|
||||
function bar() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
//// [declarationEmitTypeAliasWithTypeParameters3.d.ts]
|
||||
declare type Foo<T> = {
|
||||
foo<U>(): Foo<U>;
|
||||
};
|
||||
declare function bar(): {
|
||||
foo<U>(): any;
|
||||
};
|
||||
@ -0,0 +1,20 @@
|
||||
=== tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters3.ts ===
|
||||
|
||||
type Foo<T> = {
|
||||
>Foo : Symbol(Foo, Decl(declarationEmitTypeAliasWithTypeParameters3.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(declarationEmitTypeAliasWithTypeParameters3.ts, 1, 9))
|
||||
|
||||
foo<U>(): Foo<U>
|
||||
>foo : Symbol(foo, Decl(declarationEmitTypeAliasWithTypeParameters3.ts, 1, 15))
|
||||
>U : Symbol(U, Decl(declarationEmitTypeAliasWithTypeParameters3.ts, 2, 8))
|
||||
>Foo : Symbol(Foo, Decl(declarationEmitTypeAliasWithTypeParameters3.ts, 0, 0))
|
||||
>U : Symbol(U, Decl(declarationEmitTypeAliasWithTypeParameters3.ts, 2, 8))
|
||||
|
||||
};
|
||||
function bar() {
|
||||
>bar : Symbol(bar, Decl(declarationEmitTypeAliasWithTypeParameters3.ts, 3, 2))
|
||||
|
||||
return {} as Foo<number>;
|
||||
>Foo : Symbol(Foo, Decl(declarationEmitTypeAliasWithTypeParameters3.ts, 0, 0))
|
||||
}
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
=== tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters3.ts ===
|
||||
|
||||
type Foo<T> = {
|
||||
>Foo : Foo<T>
|
||||
>T : T
|
||||
|
||||
foo<U>(): Foo<U>
|
||||
>foo : <U>() => { foo<U>(): any; }
|
||||
>U : U
|
||||
>Foo : Foo<T>
|
||||
>U : U
|
||||
|
||||
};
|
||||
function bar() {
|
||||
>bar : () => { foo<U>(): any; }
|
||||
|
||||
return {} as Foo<number>;
|
||||
>{} as Foo<number> : { foo<U>(): any; }
|
||||
>{} : {}
|
||||
>Foo : Foo<T>
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
//// [declarationEmitTypeAliasWithTypeParameters4.ts]
|
||||
|
||||
type Foo<T, Y> = {
|
||||
foo<U, J>(): Foo<U, J>
|
||||
};
|
||||
type SubFoo<R> = Foo<string, R>;
|
||||
|
||||
function foo() {
|
||||
return {} as SubFoo<number>;
|
||||
}
|
||||
|
||||
|
||||
//// [declarationEmitTypeAliasWithTypeParameters4.js]
|
||||
function foo() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
//// [declarationEmitTypeAliasWithTypeParameters4.d.ts]
|
||||
declare type Foo<T, Y> = {
|
||||
foo<U, J>(): Foo<U, J>;
|
||||
};
|
||||
declare type SubFoo<R> = Foo<string, R>;
|
||||
declare function foo(): {
|
||||
foo<U, J>(): any;
|
||||
};
|
||||
@ -0,0 +1,29 @@
|
||||
=== tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters4.ts ===
|
||||
|
||||
type Foo<T, Y> = {
|
||||
>Foo : Symbol(Foo, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 1, 9))
|
||||
>Y : Symbol(Y, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 1, 11))
|
||||
|
||||
foo<U, J>(): Foo<U, J>
|
||||
>foo : Symbol(foo, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 1, 18))
|
||||
>U : Symbol(U, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 2, 8))
|
||||
>J : Symbol(J, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 2, 10))
|
||||
>Foo : Symbol(Foo, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 0, 0))
|
||||
>U : Symbol(U, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 2, 8))
|
||||
>J : Symbol(J, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 2, 10))
|
||||
|
||||
};
|
||||
type SubFoo<R> = Foo<string, R>;
|
||||
>SubFoo : Symbol(SubFoo, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 3, 2))
|
||||
>R : Symbol(R, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 4, 12))
|
||||
>Foo : Symbol(Foo, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 0, 0))
|
||||
>R : Symbol(R, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 4, 12))
|
||||
|
||||
function foo() {
|
||||
>foo : Symbol(foo, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 4, 32))
|
||||
|
||||
return {} as SubFoo<number>;
|
||||
>SubFoo : Symbol(SubFoo, Decl(declarationEmitTypeAliasWithTypeParameters4.ts, 3, 2))
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
=== tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters4.ts ===
|
||||
|
||||
type Foo<T, Y> = {
|
||||
>Foo : Foo<T, Y>
|
||||
>T : T
|
||||
>Y : Y
|
||||
|
||||
foo<U, J>(): Foo<U, J>
|
||||
>foo : <U, J>() => { foo<U, J>(): any; }
|
||||
>U : U
|
||||
>J : J
|
||||
>Foo : Foo<T, Y>
|
||||
>U : U
|
||||
>J : J
|
||||
|
||||
};
|
||||
type SubFoo<R> = Foo<string, R>;
|
||||
>SubFoo : { foo<U, J>(): any; }
|
||||
>R : R
|
||||
>Foo : Foo<T, Y>
|
||||
>R : R
|
||||
|
||||
function foo() {
|
||||
>foo : () => { foo<U, J>(): any; }
|
||||
|
||||
return {} as SubFoo<number>;
|
||||
>{} as SubFoo<number> : { foo<U, J>(): any; }
|
||||
>{} : {}
|
||||
>SubFoo : { foo<U, J>(): any; }
|
||||
}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters5.ts(5,25): error TS4081: Exported type alias 'SubFoo' has or is using private name 'Foo'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters5.ts (1 errors) ====
|
||||
|
||||
type Foo<T, Y> = {
|
||||
foo<U, J>(): Foo<U, J>
|
||||
};
|
||||
export type SubFoo<R> = Foo<string, R>;
|
||||
~~~
|
||||
!!! error TS4081: Exported type alias 'SubFoo' has or is using private name 'Foo'.
|
||||
|
||||
function foo() {
|
||||
return {} as SubFoo<number>;
|
||||
}
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
//// [declarationEmitTypeAliasWithTypeParameters5.ts]
|
||||
|
||||
type Foo<T, Y> = {
|
||||
foo<U, J>(): Foo<U, J>
|
||||
};
|
||||
export type SubFoo<R> = Foo<string, R>;
|
||||
|
||||
function foo() {
|
||||
return {} as SubFoo<number>;
|
||||
}
|
||||
|
||||
|
||||
//// [declarationEmitTypeAliasWithTypeParameters5.js]
|
||||
"use strict";
|
||||
function foo() {
|
||||
return {};
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
//// [declarationEmitTypeAliasWithTypeParameters6.ts]
|
||||
|
||||
type Foo<T, Y> = {
|
||||
foo<U, J>(): Foo<U, J>
|
||||
};
|
||||
type SubFoo<R, S> = Foo<S, R>;
|
||||
|
||||
function foo() {
|
||||
return {} as SubFoo<number, string>;
|
||||
}
|
||||
|
||||
|
||||
//// [declarationEmitTypeAliasWithTypeParameters6.js]
|
||||
function foo() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
//// [declarationEmitTypeAliasWithTypeParameters6.d.ts]
|
||||
declare type Foo<T, Y> = {
|
||||
foo<U, J>(): Foo<U, J>;
|
||||
};
|
||||
declare type SubFoo<R, S> = Foo<S, R>;
|
||||
declare function foo(): {
|
||||
foo<U, J>(): any;
|
||||
};
|
||||
@ -0,0 +1,31 @@
|
||||
=== tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters6.ts ===
|
||||
|
||||
type Foo<T, Y> = {
|
||||
>Foo : Symbol(Foo, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 1, 9))
|
||||
>Y : Symbol(Y, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 1, 11))
|
||||
|
||||
foo<U, J>(): Foo<U, J>
|
||||
>foo : Symbol(foo, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 1, 18))
|
||||
>U : Symbol(U, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 2, 8))
|
||||
>J : Symbol(J, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 2, 10))
|
||||
>Foo : Symbol(Foo, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 0, 0))
|
||||
>U : Symbol(U, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 2, 8))
|
||||
>J : Symbol(J, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 2, 10))
|
||||
|
||||
};
|
||||
type SubFoo<R, S> = Foo<S, R>;
|
||||
>SubFoo : Symbol(SubFoo, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 3, 2))
|
||||
>R : Symbol(R, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 4, 12))
|
||||
>S : Symbol(S, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 4, 14))
|
||||
>Foo : Symbol(Foo, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 0, 0))
|
||||
>S : Symbol(S, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 4, 14))
|
||||
>R : Symbol(R, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 4, 12))
|
||||
|
||||
function foo() {
|
||||
>foo : Symbol(foo, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 4, 30))
|
||||
|
||||
return {} as SubFoo<number, string>;
|
||||
>SubFoo : Symbol(SubFoo, Decl(declarationEmitTypeAliasWithTypeParameters6.ts, 3, 2))
|
||||
}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
=== tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters6.ts ===
|
||||
|
||||
type Foo<T, Y> = {
|
||||
>Foo : Foo<T, Y>
|
||||
>T : T
|
||||
>Y : Y
|
||||
|
||||
foo<U, J>(): Foo<U, J>
|
||||
>foo : <U, J>() => { foo<U, J>(): any; }
|
||||
>U : U
|
||||
>J : J
|
||||
>Foo : Foo<T, Y>
|
||||
>U : U
|
||||
>J : J
|
||||
|
||||
};
|
||||
type SubFoo<R, S> = Foo<S, R>;
|
||||
>SubFoo : { foo<U, J>(): any; }
|
||||
>R : R
|
||||
>S : S
|
||||
>Foo : Foo<T, Y>
|
||||
>S : S
|
||||
>R : R
|
||||
|
||||
function foo() {
|
||||
>foo : () => { foo<U, J>(): any; }
|
||||
|
||||
return {} as SubFoo<number, string>;
|
||||
>{} as SubFoo<number, string> : { foo<U, J>(): any; }
|
||||
>{} : {}
|
||||
>SubFoo : { foo<U, J>(): any; }
|
||||
}
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
// @declaration: true
|
||||
|
||||
export type Bar<X, Y, Z> = () => [X, Y, Z];
|
||||
export type Baz<M, N> = Bar<M, string, N>;
|
||||
export type Baa<Y> = Baz<boolean, Y>;
|
||||
export const y = (x: Baa<number>) => 1
|
||||
@ -0,0 +1,8 @@
|
||||
// @declaration: true
|
||||
|
||||
type Foo<T> = {
|
||||
foo<U>(): Foo<U>
|
||||
};
|
||||
function bar() {
|
||||
return {} as Foo<number>;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
// @declaration: true
|
||||
|
||||
type Foo<T, Y> = {
|
||||
foo<U, J>(): Foo<U, J>
|
||||
};
|
||||
type SubFoo<R> = Foo<string, R>;
|
||||
|
||||
function foo() {
|
||||
return {} as SubFoo<number>;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
// @declaration: true
|
||||
|
||||
type Foo<T, Y> = {
|
||||
foo<U, J>(): Foo<U, J>
|
||||
};
|
||||
export type SubFoo<R> = Foo<string, R>;
|
||||
|
||||
function foo() {
|
||||
return {} as SubFoo<number>;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
// @declaration: true
|
||||
|
||||
type Foo<T, Y> = {
|
||||
foo<U, J>(): Foo<U, J>
|
||||
};
|
||||
type SubFoo<R, S> = Foo<S, R>;
|
||||
|
||||
function foo() {
|
||||
return {} as SubFoo<number, string>;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user