Skip to content

Commit

Permalink
Preserve alias symbols on references to type aliases via imports (#51152
Browse files Browse the repository at this point in the history
)

* Preserve alias symbols on references to type aliases via imports

* Fix lint
  • Loading branch information
weswigham authored Nov 18, 2022
1 parent 00dc0b6 commit a3092c7
Show file tree
Hide file tree
Showing 9 changed files with 696 additions and 22 deletions.
20 changes: 18 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
Expand Up @@ -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 ===

Expand Down
Original file line number Diff line number Diff line change
@@ -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>;
Loading

0 comments on commit a3092c7

Please sign in to comment.