Preserve alias symbols on references to type aliases via imports (#51152)

* Preserve alias symbols on references to type aliases via imports

* Fix lint
This commit is contained in:
Wesley Wigham 2022-11-17 21:25:31 -08:00 committed by GitHub
parent 00dc0b6674
commit a3092c798a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 696 additions and 22 deletions

View File

@ -14888,8 +14888,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// accessible--which in turn may lead to a large structural expansion of the type when generating
// a .d.ts file. See #43622 for an example.
const aliasSymbol = getAliasSymbolForTypeNode(node);
const newAliasSymbol = aliasSymbol && (isLocalTypeAlias(symbol) || !isLocalTypeAlias(aliasSymbol)) ? aliasSymbol : undefined;
return getTypeAliasInstantiation(symbol, typeArgumentsFromTypeReferenceNode(node), newAliasSymbol, getTypeArgumentsForAliasSymbol(newAliasSymbol));
let newAliasSymbol = aliasSymbol && (isLocalTypeAlias(symbol) || !isLocalTypeAlias(aliasSymbol)) ? aliasSymbol : undefined;
let aliasTypeArguments: Type[] | undefined;
if (newAliasSymbol) {
aliasTypeArguments = getTypeArgumentsForAliasSymbol(newAliasSymbol);
}
else if (isTypeReferenceType(node)) {
const aliasSymbol = resolveTypeReferenceName(node, SymbolFlags.Alias, /*ignoreErrors*/ true);
// refers to an alias import/export/reexport - by making sure we use the target as an aliasSymbol,
// we ensure the exported symbol is used to refer to the type when it's reserialized later
if (aliasSymbol && aliasSymbol !== unknownSymbol) {
const resolved = resolveAlias(aliasSymbol);
if (resolved && resolved.flags & SymbolFlags.TypeAlias) {
newAliasSymbol = resolved;
aliasTypeArguments = typeArgumentsFromTypeReferenceNode(node);
}
}
}
return getTypeAliasInstantiation(symbol, typeArgumentsFromTypeReferenceNode(node), newAliasSymbol, aliasTypeArguments);
}
return checkNoTypeArguments(node, symbol) ? type : errorType;
}

View File

@ -80,7 +80,7 @@ import { Component } from 'react';
export declare function getComp(): Component;
//// [inferred-comp-export.d.ts]
export declare const obj: {
comp: import("react").Component<any, {}, {}>;
comp: import("react").Component;
};
//// [some-other-file.d.ts]
export * from '@emotion/core';

View File

@ -36,24 +36,24 @@ export function getComp(): Component {
>getComp : () => Component
return {} as any as Component
>{} as any as Component : Component<any, {}, {}>
>{} as any as Component : Component
>{} as any : any
>{} : {}
}
=== tests/cases/compiler/src/inferred-comp-export.ts ===
import { getComp } from "./get-comp";
>getComp : () => import("tests/cases/compiler/node_modules/@types/react/index").Component<any, {}, {}>
>getComp : () => import("tests/cases/compiler/node_modules/@types/react/index").Component
// this shouldn't need any triple-slash references - it should have a direct import to `react` and that's it
// This issue (#35343) _only_ reproduces in the test harness when the file in question is in a subfolder
export const obj = {
>obj : { comp: import("tests/cases/compiler/node_modules/@types/react/index").Component<any, {}, {}>; }
>{ comp: getComp()} : { comp: import("tests/cases/compiler/node_modules/@types/react/index").Component<any, {}, {}>; }
>obj : { comp: import("tests/cases/compiler/node_modules/@types/react/index").Component; }
>{ comp: getComp()} : { comp: import("tests/cases/compiler/node_modules/@types/react/index").Component; }
comp: getComp()
>comp : import("tests/cases/compiler/node_modules/@types/react/index").Component<any, {}, {}>
>getComp() : import("tests/cases/compiler/node_modules/@types/react/index").Component<any, {}, {}>
>getComp : () => import("tests/cases/compiler/node_modules/@types/react/index").Component<any, {}, {}>
>comp : import("tests/cases/compiler/node_modules/@types/react/index").Component
>getComp() : import("tests/cases/compiler/node_modules/@types/react/index").Component
>getComp : () => import("tests/cases/compiler/node_modules/@types/react/index").Component
}
=== tests/cases/compiler/src/some-other-file.ts ===

View File

@ -0,0 +1,116 @@
//// [tests/cases/compiler/declarationEmitRecursiveConditionalAliasPreserved.ts] ////
//// [input.d.ts]
type _BuildPowersOf2LengthArrays<
Length extends number,
AccumulatedArray extends never[][],
> = AccumulatedArray[0][Length] extends never
? AccumulatedArray
: _BuildPowersOf2LengthArrays<
Length,
[[...AccumulatedArray[0], ...AccumulatedArray[0]], ...AccumulatedArray]
>;
type _ConcatLargestUntilDone<
Length extends number,
AccumulatedArray extends never[][],
NextArray extends never[],
> = NextArray['length'] extends Length
? NextArray
: [...AccumulatedArray[0], ...NextArray][Length] extends never
? _ConcatLargestUntilDone<
Length,
AccumulatedArray extends [AccumulatedArray[0], ...infer U]
? U extends never[][]
? U
: never
: never,
NextArray
>
: _ConcatLargestUntilDone<
Length,
AccumulatedArray extends [AccumulatedArray[0], ...infer U]
? U extends never[][]
? U
: never
: never,
[...AccumulatedArray[0], ...NextArray]
>
type _Replace<R extends unknown[], T> = { [K in keyof R]: T };
export type TupleOf<Type, Length extends number> = number extends Length
? Type[]
: {
// in case Length is a union
[LengthKey in Length]: _BuildPowersOf2LengthArrays<
LengthKey,
[[never]]
> extends infer TwoDimensionalArray
? TwoDimensionalArray extends never[][]
? _Replace<_ConcatLargestUntilDone<LengthKey, TwoDimensionalArray, []>, Type>
: never
: never
}[Length];
export type Subtract<N1 extends number, N2 extends number> = TupleOf<never, N1> extends [
...TupleOf<never, N2>,
...infer R,
]
? R['length']
: never;
export type Decrement<T extends number> = Subtract<T, 1>;
export type Add<N1 extends number, N2 extends number> = [
...TupleOf<never, N1>,
...TupleOf<never, N2>,
]['length'] &
// intersection to suppress compiler narrowing bug
number;
type _MultiAdd<
Num extends number,
Accumulator extends number,
IterationsLeft extends number,
> = IterationsLeft extends 0
? Accumulator
: _MultiAdd<Num, Add<Num, Accumulator>, Decrement<IterationsLeft>>
export type Multiply<N1 extends number, N2 extends number> = number extends N1 | N2
? number
: {
[K2 in N2]: { [K1 in N1]: _MultiAdd<K1, 0, N2> }[N1]
}[N2]
type PowerTailRec<
Num extends number,
PowerOf extends number,
Result extends number,
> = number extends PowerOf
? number
: PowerOf extends 0
? Result
: PowerTailRec<Num, Decrement<PowerOf>, Multiply<Result, Num>>;
export type Power<Num extends number, PowerOf extends number> = PowerTailRec<Num, PowerOf, 1>;
//// [a.tsx]
import { Power } from "./input";
export const power = <Num extends number, PowerOf extends number>(
num: Num,
powerOf: PowerOf
): Power<Num, PowerOf> => (num ** powerOf) as never;
//// [a.js]
"use strict";
exports.__esModule = true;
exports.power = void 0;
var power = function (num, powerOf) { return (Math.pow(num, powerOf)); };
exports.power = power;
//// [a.d.ts]
import { Power } from "./input";
export declare const power: <Num extends number, PowerOf extends number>(num: Num, powerOf: PowerOf) => Power<Num, PowerOf>;

View File

@ -0,0 +1,303 @@
=== tests/cases/compiler/input.d.ts ===
type _BuildPowersOf2LengthArrays<
>_BuildPowersOf2LengthArrays : Symbol(_BuildPowersOf2LengthArrays, Decl(input.d.ts, 0, 0))
Length extends number,
>Length : Symbol(Length, Decl(input.d.ts, 0, 33))
AccumulatedArray extends never[][],
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 1, 26))
> = AccumulatedArray[0][Length] extends never
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 1, 26))
>Length : Symbol(Length, Decl(input.d.ts, 0, 33))
? AccumulatedArray
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 1, 26))
: _BuildPowersOf2LengthArrays<
>_BuildPowersOf2LengthArrays : Symbol(_BuildPowersOf2LengthArrays, Decl(input.d.ts, 0, 0))
Length,
>Length : Symbol(Length, Decl(input.d.ts, 0, 33))
[[...AccumulatedArray[0], ...AccumulatedArray[0]], ...AccumulatedArray]
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 1, 26))
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 1, 26))
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 1, 26))
>;
type _ConcatLargestUntilDone<
>_ConcatLargestUntilDone : Symbol(_ConcatLargestUntilDone, Decl(input.d.ts, 8, 6))
Length extends number,
>Length : Symbol(Length, Decl(input.d.ts, 10, 29))
AccumulatedArray extends never[][],
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 11, 26))
NextArray extends never[],
>NextArray : Symbol(NextArray, Decl(input.d.ts, 12, 39))
> = NextArray['length'] extends Length
>NextArray : Symbol(NextArray, Decl(input.d.ts, 12, 39))
>Length : Symbol(Length, Decl(input.d.ts, 10, 29))
? NextArray
>NextArray : Symbol(NextArray, Decl(input.d.ts, 12, 39))
: [...AccumulatedArray[0], ...NextArray][Length] extends never
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 11, 26))
>NextArray : Symbol(NextArray, Decl(input.d.ts, 12, 39))
>Length : Symbol(Length, Decl(input.d.ts, 10, 29))
? _ConcatLargestUntilDone<
>_ConcatLargestUntilDone : Symbol(_ConcatLargestUntilDone, Decl(input.d.ts, 8, 6))
Length,
>Length : Symbol(Length, Decl(input.d.ts, 10, 29))
AccumulatedArray extends [AccumulatedArray[0], ...infer U]
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 11, 26))
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 11, 26))
>U : Symbol(U, Decl(input.d.ts, 19, 63))
? U extends never[][]
>U : Symbol(U, Decl(input.d.ts, 19, 63))
? U
>U : Symbol(U, Decl(input.d.ts, 19, 63))
: never
: never,
NextArray
>NextArray : Symbol(NextArray, Decl(input.d.ts, 12, 39))
>
: _ConcatLargestUntilDone<
>_ConcatLargestUntilDone : Symbol(_ConcatLargestUntilDone, Decl(input.d.ts, 8, 6))
Length,
>Length : Symbol(Length, Decl(input.d.ts, 10, 29))
AccumulatedArray extends [AccumulatedArray[0], ...infer U]
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 11, 26))
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 11, 26))
>U : Symbol(U, Decl(input.d.ts, 28, 63))
? U extends never[][]
>U : Symbol(U, Decl(input.d.ts, 28, 63))
? U
>U : Symbol(U, Decl(input.d.ts, 28, 63))
: never
: never,
[...AccumulatedArray[0], ...NextArray]
>AccumulatedArray : Symbol(AccumulatedArray, Decl(input.d.ts, 11, 26))
>NextArray : Symbol(NextArray, Decl(input.d.ts, 12, 39))
>
type _Replace<R extends unknown[], T> = { [K in keyof R]: T };
>_Replace : Symbol(_Replace, Decl(input.d.ts, 34, 5))
>R : Symbol(R, Decl(input.d.ts, 36, 14))
>T : Symbol(T, Decl(input.d.ts, 36, 34))
>K : Symbol(K, Decl(input.d.ts, 36, 43))
>R : Symbol(R, Decl(input.d.ts, 36, 14))
>T : Symbol(T, Decl(input.d.ts, 36, 34))
export type TupleOf<Type, Length extends number> = number extends Length
>TupleOf : Symbol(TupleOf, Decl(input.d.ts, 36, 62))
>Type : Symbol(Type, Decl(input.d.ts, 38, 20))
>Length : Symbol(Length, Decl(input.d.ts, 38, 25))
>Length : Symbol(Length, Decl(input.d.ts, 38, 25))
? Type[]
>Type : Symbol(Type, Decl(input.d.ts, 38, 20))
: {
// in case Length is a union
[LengthKey in Length]: _BuildPowersOf2LengthArrays<
>LengthKey : Symbol(LengthKey, Decl(input.d.ts, 42, 9))
>Length : Symbol(Length, Decl(input.d.ts, 38, 25))
>_BuildPowersOf2LengthArrays : Symbol(_BuildPowersOf2LengthArrays, Decl(input.d.ts, 0, 0))
LengthKey,
>LengthKey : Symbol(LengthKey, Decl(input.d.ts, 42, 9))
[[never]]
> extends infer TwoDimensionalArray
>TwoDimensionalArray : Symbol(TwoDimensionalArray, Decl(input.d.ts, 45, 23))
? TwoDimensionalArray extends never[][]
>TwoDimensionalArray : Symbol(TwoDimensionalArray, Decl(input.d.ts, 45, 23))
? _Replace<_ConcatLargestUntilDone<LengthKey, TwoDimensionalArray, []>, Type>
>_Replace : Symbol(_Replace, Decl(input.d.ts, 34, 5))
>_ConcatLargestUntilDone : Symbol(_ConcatLargestUntilDone, Decl(input.d.ts, 8, 6))
>LengthKey : Symbol(LengthKey, Decl(input.d.ts, 42, 9))
>TwoDimensionalArray : Symbol(TwoDimensionalArray, Decl(input.d.ts, 45, 23))
>Type : Symbol(Type, Decl(input.d.ts, 38, 20))
: never
: never
}[Length];
>Length : Symbol(Length, Decl(input.d.ts, 38, 25))
export type Subtract<N1 extends number, N2 extends number> = TupleOf<never, N1> extends [
>Subtract : Symbol(Subtract, Decl(input.d.ts, 50, 14))
>N1 : Symbol(N1, Decl(input.d.ts, 52, 21))
>N2 : Symbol(N2, Decl(input.d.ts, 52, 39))
>TupleOf : Symbol(TupleOf, Decl(input.d.ts, 36, 62))
>N1 : Symbol(N1, Decl(input.d.ts, 52, 21))
...TupleOf<never, N2>,
>TupleOf : Symbol(TupleOf, Decl(input.d.ts, 36, 62))
>N2 : Symbol(N2, Decl(input.d.ts, 52, 39))
...infer R,
>R : Symbol(R, Decl(input.d.ts, 54, 12))
]
? R['length']
>R : Symbol(R, Decl(input.d.ts, 54, 12))
: never;
export type Decrement<T extends number> = Subtract<T, 1>;
>Decrement : Symbol(Decrement, Decl(input.d.ts, 57, 12))
>T : Symbol(T, Decl(input.d.ts, 59, 22))
>Subtract : Symbol(Subtract, Decl(input.d.ts, 50, 14))
>T : Symbol(T, Decl(input.d.ts, 59, 22))
export type Add<N1 extends number, N2 extends number> = [
>Add : Symbol(Add, Decl(input.d.ts, 59, 57))
>N1 : Symbol(N1, Decl(input.d.ts, 61, 16))
>N2 : Symbol(N2, Decl(input.d.ts, 61, 34))
...TupleOf<never, N1>,
>TupleOf : Symbol(TupleOf, Decl(input.d.ts, 36, 62))
>N1 : Symbol(N1, Decl(input.d.ts, 61, 16))
...TupleOf<never, N2>,
>TupleOf : Symbol(TupleOf, Decl(input.d.ts, 36, 62))
>N2 : Symbol(N2, Decl(input.d.ts, 61, 34))
]['length'] &
// intersection to suppress compiler narrowing bug
number;
type _MultiAdd<
>_MultiAdd : Symbol(_MultiAdd, Decl(input.d.ts, 66, 11))
Num extends number,
>Num : Symbol(Num, Decl(input.d.ts, 68, 15))
Accumulator extends number,
>Accumulator : Symbol(Accumulator, Decl(input.d.ts, 69, 23))
IterationsLeft extends number,
>IterationsLeft : Symbol(IterationsLeft, Decl(input.d.ts, 70, 31))
> = IterationsLeft extends 0
>IterationsLeft : Symbol(IterationsLeft, Decl(input.d.ts, 70, 31))
? Accumulator
>Accumulator : Symbol(Accumulator, Decl(input.d.ts, 69, 23))
: _MultiAdd<Num, Add<Num, Accumulator>, Decrement<IterationsLeft>>
>_MultiAdd : Symbol(_MultiAdd, Decl(input.d.ts, 66, 11))
>Num : Symbol(Num, Decl(input.d.ts, 68, 15))
>Add : Symbol(Add, Decl(input.d.ts, 59, 57))
>Num : Symbol(Num, Decl(input.d.ts, 68, 15))
>Accumulator : Symbol(Accumulator, Decl(input.d.ts, 69, 23))
>Decrement : Symbol(Decrement, Decl(input.d.ts, 57, 12))
>IterationsLeft : Symbol(IterationsLeft, Decl(input.d.ts, 70, 31))
export type Multiply<N1 extends number, N2 extends number> = number extends N1 | N2
>Multiply : Symbol(Multiply, Decl(input.d.ts, 74, 70))
>N1 : Symbol(N1, Decl(input.d.ts, 76, 21))
>N2 : Symbol(N2, Decl(input.d.ts, 76, 39))
>N1 : Symbol(N1, Decl(input.d.ts, 76, 21))
>N2 : Symbol(N2, Decl(input.d.ts, 76, 39))
? number
: {
[K2 in N2]: { [K1 in N1]: _MultiAdd<K1, 0, N2> }[N1]
>K2 : Symbol(K2, Decl(input.d.ts, 79, 9))
>N2 : Symbol(N2, Decl(input.d.ts, 76, 39))
>K1 : Symbol(K1, Decl(input.d.ts, 79, 23))
>N1 : Symbol(N1, Decl(input.d.ts, 76, 21))
>_MultiAdd : Symbol(_MultiAdd, Decl(input.d.ts, 66, 11))
>K1 : Symbol(K1, Decl(input.d.ts, 79, 23))
>N2 : Symbol(N2, Decl(input.d.ts, 76, 39))
>N1 : Symbol(N1, Decl(input.d.ts, 76, 21))
}[N2]
>N2 : Symbol(N2, Decl(input.d.ts, 76, 39))
type PowerTailRec<
>PowerTailRec : Symbol(PowerTailRec, Decl(input.d.ts, 80, 9))
Num extends number,
>Num : Symbol(Num, Decl(input.d.ts, 82, 18))
PowerOf extends number,
>PowerOf : Symbol(PowerOf, Decl(input.d.ts, 83, 23))
Result extends number,
>Result : Symbol(Result, Decl(input.d.ts, 84, 27))
> = number extends PowerOf
>PowerOf : Symbol(PowerOf, Decl(input.d.ts, 83, 23))
? number
: PowerOf extends 0
>PowerOf : Symbol(PowerOf, Decl(input.d.ts, 83, 23))
? Result
>Result : Symbol(Result, Decl(input.d.ts, 84, 27))
: PowerTailRec<Num, Decrement<PowerOf>, Multiply<Result, Num>>;
>PowerTailRec : Symbol(PowerTailRec, Decl(input.d.ts, 80, 9))
>Num : Symbol(Num, Decl(input.d.ts, 82, 18))
>Decrement : Symbol(Decrement, Decl(input.d.ts, 57, 12))
>PowerOf : Symbol(PowerOf, Decl(input.d.ts, 83, 23))
>Multiply : Symbol(Multiply, Decl(input.d.ts, 74, 70))
>Result : Symbol(Result, Decl(input.d.ts, 84, 27))
>Num : Symbol(Num, Decl(input.d.ts, 82, 18))
export type Power<Num extends number, PowerOf extends number> = PowerTailRec<Num, PowerOf, 1>;
>Power : Symbol(Power, Decl(input.d.ts, 90, 67))
>Num : Symbol(Num, Decl(input.d.ts, 92, 18))
>PowerOf : Symbol(PowerOf, Decl(input.d.ts, 92, 37))
>PowerTailRec : Symbol(PowerTailRec, Decl(input.d.ts, 80, 9))
>Num : Symbol(Num, Decl(input.d.ts, 92, 18))
>PowerOf : Symbol(PowerOf, Decl(input.d.ts, 92, 37))
=== tests/cases/compiler/a.tsx ===
import { Power } from "./input";
>Power : Symbol(Power, Decl(a.tsx, 0, 8))
export const power = <Num extends number, PowerOf extends number>(
>power : Symbol(power, Decl(a.tsx, 2, 12))
>Num : Symbol(Num, Decl(a.tsx, 2, 22))
>PowerOf : Symbol(PowerOf, Decl(a.tsx, 2, 41))
num: Num,
>num : Symbol(num, Decl(a.tsx, 2, 66))
>Num : Symbol(Num, Decl(a.tsx, 2, 22))
powerOf: PowerOf
>powerOf : Symbol(powerOf, Decl(a.tsx, 3, 13))
>PowerOf : Symbol(PowerOf, Decl(a.tsx, 2, 41))
): Power<Num, PowerOf> => (num ** powerOf) as never;
>Power : Symbol(Power, Decl(a.tsx, 0, 8))
>Num : Symbol(Num, Decl(a.tsx, 2, 22))
>PowerOf : Symbol(PowerOf, Decl(a.tsx, 2, 41))
>num : Symbol(num, Decl(a.tsx, 2, 66))
>powerOf : Symbol(powerOf, Decl(a.tsx, 3, 13))

View File

@ -0,0 +1,135 @@
=== tests/cases/compiler/input.d.ts ===
type _BuildPowersOf2LengthArrays<
>_BuildPowersOf2LengthArrays : _BuildPowersOf2LengthArrays<Length, AccumulatedArray>
Length extends number,
AccumulatedArray extends never[][],
> = AccumulatedArray[0][Length] extends never
? AccumulatedArray
: _BuildPowersOf2LengthArrays<
Length,
[[...AccumulatedArray[0], ...AccumulatedArray[0]], ...AccumulatedArray]
>;
type _ConcatLargestUntilDone<
>_ConcatLargestUntilDone : _ConcatLargestUntilDone<Length, AccumulatedArray, NextArray>
Length extends number,
AccumulatedArray extends never[][],
NextArray extends never[],
> = NextArray['length'] extends Length
? NextArray
: [...AccumulatedArray[0], ...NextArray][Length] extends never
? _ConcatLargestUntilDone<
Length,
AccumulatedArray extends [AccumulatedArray[0], ...infer U]
? U extends never[][]
? U
: never
: never,
NextArray
>
: _ConcatLargestUntilDone<
Length,
AccumulatedArray extends [AccumulatedArray[0], ...infer U]
? U extends never[][]
? U
: never
: never,
[...AccumulatedArray[0], ...NextArray]
>
type _Replace<R extends unknown[], T> = { [K in keyof R]: T };
>_Replace : _Replace<R, T>
export type TupleOf<Type, Length extends number> = number extends Length
>TupleOf : TupleOf<Type, Length>
? Type[]
: {
// in case Length is a union
[LengthKey in Length]: _BuildPowersOf2LengthArrays<
LengthKey,
[[never]]
> extends infer TwoDimensionalArray
? TwoDimensionalArray extends never[][]
? _Replace<_ConcatLargestUntilDone<LengthKey, TwoDimensionalArray, []>, Type>
: never
: never
}[Length];
export type Subtract<N1 extends number, N2 extends number> = TupleOf<never, N1> extends [
>Subtract : Subtract<N1, N2>
...TupleOf<never, N2>,
...infer R,
]
? R['length']
: never;
export type Decrement<T extends number> = Subtract<T, 1>;
>Decrement : Decrement<T>
export type Add<N1 extends number, N2 extends number> = [
>Add : Add<N1, N2>
...TupleOf<never, N1>,
...TupleOf<never, N2>,
]['length'] &
// intersection to suppress compiler narrowing bug
number;
type _MultiAdd<
>_MultiAdd : _MultiAdd<Num, Accumulator, IterationsLeft>
Num extends number,
Accumulator extends number,
IterationsLeft extends number,
> = IterationsLeft extends 0
? Accumulator
: _MultiAdd<Num, Add<Num, Accumulator>, Decrement<IterationsLeft>>
export type Multiply<N1 extends number, N2 extends number> = number extends N1 | N2
>Multiply : Multiply<N1, N2>
? number
: {
[K2 in N2]: { [K1 in N1]: _MultiAdd<K1, 0, N2> }[N1]
}[N2]
type PowerTailRec<
>PowerTailRec : PowerTailRec<Num, PowerOf, Result>
Num extends number,
PowerOf extends number,
Result extends number,
> = number extends PowerOf
? number
: PowerOf extends 0
? Result
: PowerTailRec<Num, Decrement<PowerOf>, Multiply<Result, Num>>;
export type Power<Num extends number, PowerOf extends number> = PowerTailRec<Num, PowerOf, 1>;
>Power : Power<Num, PowerOf>
=== tests/cases/compiler/a.tsx ===
import { Power } from "./input";
>Power : any
export const power = <Num extends number, PowerOf extends number>(
>power : <Num extends number, PowerOf extends number>(num: Num, powerOf: PowerOf) => Power<Num, PowerOf>
><Num extends number, PowerOf extends number>( num: Num, powerOf: PowerOf): Power<Num, PowerOf> => (num ** powerOf) as never : <Num extends number, PowerOf extends number>(num: Num, powerOf: PowerOf) => Power<Num, PowerOf>
num: Num,
>num : Num
powerOf: PowerOf
>powerOf : PowerOf
): Power<Num, PowerOf> => (num ** powerOf) as never;
>(num ** powerOf) as never : never
>(num ** powerOf) : number
>num ** powerOf : number
>num : Num
>powerOf : PowerOf

View File

@ -14,7 +14,7 @@ type ButtonBaseProps<T extends ElementType> = ComponentPropsWithRef<T> & { child
>children : React.ReactNode
function Component<T extends ElementType = 'span'>(props: ButtonBaseProps<T>) {
>Component : <T extends React.ElementType<any> = "span">(props: ButtonBaseProps<T>) => JSX.Element
>Component : <T extends React.ElementType = "span">(props: ButtonBaseProps<T>) => JSX.Element
>props : ButtonBaseProps<T>
return <></>;
@ -24,7 +24,7 @@ function Component<T extends ElementType = 'span'>(props: ButtonBaseProps<T>) {
const v1 = <Component onClick={e => e.preventDefault()} />;
>v1 : JSX.Element
><Component onClick={e => e.preventDefault()} /> : JSX.Element
>Component : <T extends React.ElementType<any> = "span">(props: ButtonBaseProps<T>) => JSX.Element
>Component : <T extends React.ElementType = "span">(props: ButtonBaseProps<T>) => JSX.Element
>onClick : (e: React.MouseEvent<HTMLSpanElement>) => void
>e => e.preventDefault() : (e: React.MouseEvent<HTMLSpanElement>) => void
>e : React.MouseEvent<HTMLSpanElement>

View File

@ -318,7 +318,7 @@ declare module "Object/ListOf" {
>__ListOf : __ListOf<O, K, LN, I>
0: __ListOf<O, Exclude<K, Key<I>>, PickIfEntry<O, LN, I>, Next<I>>;
>0 : __ListOf<O, Exclude<K, I[2]>, PickIfEntry<O, LN, I>, Next<I>>
>0 : __ListOf<O, Exclude<K, Key<I>>, PickIfEntry<O, LN, I>, Next<I>>
1: LN;
>1 : LN
@ -357,7 +357,7 @@ declare module "Object/NonNullable" {
>Keys : any
export type NonNullableFlat<O> = {
>NonNullableFlat : { [K in keyof O]: import("Union/Exclude").Exclude<O[K], null | undefined>; }
>NonNullableFlat : { [K in keyof O]: UNonNullable<O[K]>; }
[K in keyof O]: UNonNullable<O[K]>;
} & {};
@ -386,7 +386,7 @@ declare module "Object/NonNullable" {
>1 : NonNullablePart<O, depth>
0: MergeFlat<NonNullablePart<Pick<O, K>, depth>, O>;
>0 : import("Any/Compute").Compute<NonNullablePart<Pick<O, K>, depth> & import("Object/Omit")._Omit<O, keyof NonNullablePart<Pick<O, K>, depth>>>
>0 : MergeFlat<NonNullablePart<Pick<O, K>, depth>, O>
}[Implements<Keys<O>, K>] & {};
}
@ -592,7 +592,7 @@ declare module "List/Reverse" {
>__Reverse : __Reverse<L, LO, I>
0: __Reverse<L, Prepend<LO, L[Pos<I>]>, Next<I>>;
>0 : __Reverse<L, [head: L[I[3]], ...args: LO], Next<I>>
>0 : __Reverse<L, [head: L[Pos<I>], ...args: LO], Next<I>>
1: LO;
>1 : LO
@ -674,7 +674,7 @@ declare module "List/Drop" {
>DropBack : DropBack<L, N, I, LN>
0: DropBack<L, N, Prev<I>, Prepend<LN, L[Pos<I>]>>;
>0 : DropBack<L, N, Prev<I>, [head: L[I[3]], ...args: LN]>
>0 : DropBack<L, N, Prev<I>, [head: L[Pos<I>], ...args: LN]>
1: LN;
>1 : LN
@ -1211,7 +1211,7 @@ declare module "List/NonNullable" {
>NonNullable : NonNullable<L, K, depth>
1: Cast<ONonNullable<L, Key, depth>, List>;
>1 : Cast<ONonNullable<L, Key, depth>, List<any>>
>1 : Cast<ONonNullable<L, Key, depth>, List>
0: ListOf<ONonNullable<ObjectOf<L>, NumberOf<K>, depth>>;
>0 : ListOf<ONonNullable<ObjectOf<L>, NumberOf<K>, depth>>
@ -1329,7 +1329,7 @@ declare module "Function/Curry" {
>0 : _GapsOf<L1, L2, GapOf<L1, L2, LN, I>, Next<I>>
1: _Concat<LN, _Drop<L2, Key<I>>>;
>1 : import("List/Reverse")._Reverse<import("List/Reverse")._Reverse<LN, []>, _Drop<L2, I[2], "->">>
>1 : _Concat<LN, _Drop<L2, Key<I>>>
}[Extends<Pos<I>, Length<L1>>];
@ -1345,9 +1345,9 @@ declare module "Function/Curry" {
export type Curry<F extends Function> = <L extends List>(...args: Cast<L, Gaps<Parameters<F>>>) => GapsOf<L, Parameters<F>> extends infer G ? Length<Cast<G, List>> extends infer L ? L extends 0 ? Return<F> : L extends 1 ? Curry<(...args: Cast<G, List>) => Return<F>> & ((...args: Cast<G, List>) => Return<F>) : Curry<(...args: Cast<G, List>) => Return<F>> : never : never;
>Curry : Curry<F>
>args : Cast<L, Gaps<Parameters<F>>>
>args : Cast<G, List<any>>
>args : Cast<G, List<any>>
>args : Cast<G, List<any>>
>args : Cast<G, List>
>args : Cast<G, List>
>args : Cast<G, List>
}

View File

@ -0,0 +1,104 @@
// @declaration: true
// @filename: input.d.ts
type _BuildPowersOf2LengthArrays<
Length extends number,
AccumulatedArray extends never[][],
> = AccumulatedArray[0][Length] extends never
? AccumulatedArray
: _BuildPowersOf2LengthArrays<
Length,
[[...AccumulatedArray[0], ...AccumulatedArray[0]], ...AccumulatedArray]
>;
type _ConcatLargestUntilDone<
Length extends number,
AccumulatedArray extends never[][],
NextArray extends never[],
> = NextArray['length'] extends Length
? NextArray
: [...AccumulatedArray[0], ...NextArray][Length] extends never
? _ConcatLargestUntilDone<
Length,
AccumulatedArray extends [AccumulatedArray[0], ...infer U]
? U extends never[][]
? U
: never
: never,
NextArray
>
: _ConcatLargestUntilDone<
Length,
AccumulatedArray extends [AccumulatedArray[0], ...infer U]
? U extends never[][]
? U
: never
: never,
[...AccumulatedArray[0], ...NextArray]
>
type _Replace<R extends unknown[], T> = { [K in keyof R]: T };
export type TupleOf<Type, Length extends number> = number extends Length
? Type[]
: {
// in case Length is a union
[LengthKey in Length]: _BuildPowersOf2LengthArrays<
LengthKey,
[[never]]
> extends infer TwoDimensionalArray
? TwoDimensionalArray extends never[][]
? _Replace<_ConcatLargestUntilDone<LengthKey, TwoDimensionalArray, []>, Type>
: never
: never
}[Length];
export type Subtract<N1 extends number, N2 extends number> = TupleOf<never, N1> extends [
...TupleOf<never, N2>,
...infer R,
]
? R['length']
: never;
export type Decrement<T extends number> = Subtract<T, 1>;
export type Add<N1 extends number, N2 extends number> = [
...TupleOf<never, N1>,
...TupleOf<never, N2>,
]['length'] &
// intersection to suppress compiler narrowing bug
number;
type _MultiAdd<
Num extends number,
Accumulator extends number,
IterationsLeft extends number,
> = IterationsLeft extends 0
? Accumulator
: _MultiAdd<Num, Add<Num, Accumulator>, Decrement<IterationsLeft>>
export type Multiply<N1 extends number, N2 extends number> = number extends N1 | N2
? number
: {
[K2 in N2]: { [K1 in N1]: _MultiAdd<K1, 0, N2> }[N1]
}[N2]
type PowerTailRec<
Num extends number,
PowerOf extends number,
Result extends number,
> = number extends PowerOf
? number
: PowerOf extends 0
? Result
: PowerTailRec<Num, Decrement<PowerOf>, Multiply<Result, Num>>;
export type Power<Num extends number, PowerOf extends number> = PowerTailRec<Num, PowerOf, 1>;
// @filename: a.tsx
import { Power } from "./input";
export const power = <Num extends number, PowerOf extends number>(
num: Num,
powerOf: PowerOf
): Power<Num, PowerOf> => (num ** powerOf) as never;