Permit instantiation expressions in `typeof import(...)` (#52532)
This commit is contained in:
Родитель
26eced32ed
Коммит
d656487fca
|
@ -17748,11 +17748,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
function getTypeFromImportTypeNode(node: ImportTypeNode): Type {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
if (node.isTypeOf && node.typeArguments) { // Only the non-typeof form can make use of type arguments
|
||||
error(node, Diagnostics.Type_arguments_cannot_be_used_here);
|
||||
links.resolvedSymbol = unknownSymbol;
|
||||
return links.resolvedType = errorType;
|
||||
}
|
||||
if (!isLiteralImportTypeNode(node)) {
|
||||
error(node.argument, Diagnostics.String_literal_expected);
|
||||
links.resolvedSymbol = unknownSymbol;
|
||||
|
@ -17815,7 +17810,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
const resolvedSymbol = resolveSymbol(symbol);
|
||||
links.resolvedSymbol = resolvedSymbol;
|
||||
if (meaning === SymbolFlags.Value) {
|
||||
return getTypeOfSymbol(symbol); // intentionally doesn't use resolved symbol so type is cached as expected on the alias
|
||||
return getInstantiationExpressionType(getTypeOfSymbol(symbol), node); // intentionally doesn't use resolved symbol so type is cached as expected on the alias
|
||||
}
|
||||
else {
|
||||
const type = tryGetDeclaredTypeOfSymbol(resolvedSymbol); // call this first to ensure typeParameters is populated (if applicable)
|
||||
|
@ -34055,6 +34050,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
const exprType = node.kind === SyntaxKind.ExpressionWithTypeArguments ? checkExpression(node.expression) :
|
||||
isThisIdentifier(node.exprName) ? checkThisExpression(node.exprName) :
|
||||
checkExpression(node.exprName);
|
||||
return getInstantiationExpressionType(exprType, node);
|
||||
}
|
||||
|
||||
function getInstantiationExpressionType(exprType: Type, node: NodeWithTypeArguments) {
|
||||
const typeArguments = node.typeArguments;
|
||||
if (exprType === silentNeverType || isErrorType(exprType) || !some(typeArguments)) {
|
||||
return exprType;
|
||||
|
|
|
@ -1076,10 +1076,6 @@
|
|||
"category": "Error",
|
||||
"code": 1341
|
||||
},
|
||||
"Type arguments cannot be used here.": {
|
||||
"category": "Error",
|
||||
"code": 1342
|
||||
},
|
||||
"The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node16', or 'nodenext'.": {
|
||||
"category": "Error",
|
||||
"code": 1343
|
||||
|
|
|
@ -6409,7 +6409,7 @@ export interface AnonymousType extends ObjectType {
|
|||
|
||||
/** @internal */
|
||||
export interface InstantiationExpressionType extends AnonymousType {
|
||||
node: ExpressionWithTypeArguments | TypeQueryNode;
|
||||
node: NodeWithTypeArguments;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
|
|
@ -664,7 +664,6 @@ Info 32 [00:01:13.000] response:
|
|||
"1339",
|
||||
"1340",
|
||||
"1341",
|
||||
"1342",
|
||||
"1343",
|
||||
"1344",
|
||||
"1345",
|
||||
|
@ -2013,7 +2012,6 @@ Info 38 [00:01:19.000] response:
|
|||
"1339",
|
||||
"1340",
|
||||
"1341",
|
||||
"1342",
|
||||
"1343",
|
||||
"1344",
|
||||
"1345",
|
||||
|
@ -3274,7 +3272,6 @@ Info 40 [00:01:21.000] response:
|
|||
"1339",
|
||||
"1340",
|
||||
"1341",
|
||||
"1342",
|
||||
"1343",
|
||||
"1344",
|
||||
"1345",
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//// [tests/cases/compiler/typeofImportInstantiationExpression.ts] ////
|
||||
|
||||
//// [input.ts]
|
||||
// @strict
|
||||
|
||||
// Repro from #52248
|
||||
|
||||
interface Arg<T = any, Params extends Record<string, any> = Record<string, any>> {
|
||||
"__is_argument__"?: true;
|
||||
meta?: T;
|
||||
params?: Params;
|
||||
}
|
||||
|
||||
export function myFunction<T = any, U extends Record<string, any> = Record<string, any>>(arg: Arg<T, U>) { return (arg.params || {}) as U }
|
||||
|
||||
//// [main.ts]
|
||||
type T1 = typeof import('./input.js').myFunction;
|
||||
type T2 = typeof import('./input.js').myFunction<any, { slug: 'hello' }>;
|
||||
|
||||
|
||||
//// [input.js]
|
||||
"use strict";
|
||||
// @strict
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.myFunction = void 0;
|
||||
function myFunction(arg) { return (arg.params || {}); }
|
||||
exports.myFunction = myFunction;
|
||||
//// [main.js]
|
|
@ -0,0 +1,49 @@
|
|||
=== tests/cases/compiler/input.ts ===
|
||||
// @strict
|
||||
|
||||
// Repro from #52248
|
||||
|
||||
interface Arg<T = any, Params extends Record<string, any> = Record<string, any>> {
|
||||
>Arg : Symbol(Arg, Decl(input.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(input.ts, 4, 14))
|
||||
>Params : Symbol(Params, Decl(input.ts, 4, 22))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
"__is_argument__"?: true;
|
||||
>"__is_argument__" : Symbol(Arg["__is_argument__"], Decl(input.ts, 4, 82))
|
||||
|
||||
meta?: T;
|
||||
>meta : Symbol(Arg.meta, Decl(input.ts, 5, 29))
|
||||
>T : Symbol(T, Decl(input.ts, 4, 14))
|
||||
|
||||
params?: Params;
|
||||
>params : Symbol(Arg.params, Decl(input.ts, 6, 13))
|
||||
>Params : Symbol(Params, Decl(input.ts, 4, 22))
|
||||
}
|
||||
|
||||
export function myFunction<T = any, U extends Record<string, any> = Record<string, any>>(arg: Arg<T, U>) { return (arg.params || {}) as U }
|
||||
>myFunction : Symbol(myFunction, Decl(input.ts, 8, 1))
|
||||
>T : Symbol(T, Decl(input.ts, 10, 27))
|
||||
>U : Symbol(U, Decl(input.ts, 10, 35))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>arg : Symbol(arg, Decl(input.ts, 10, 89))
|
||||
>Arg : Symbol(Arg, Decl(input.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(input.ts, 10, 27))
|
||||
>U : Symbol(U, Decl(input.ts, 10, 35))
|
||||
>arg.params : Symbol(Arg.params, Decl(input.ts, 6, 13))
|
||||
>arg : Symbol(arg, Decl(input.ts, 10, 89))
|
||||
>params : Symbol(Arg.params, Decl(input.ts, 6, 13))
|
||||
>U : Symbol(U, Decl(input.ts, 10, 35))
|
||||
|
||||
=== tests/cases/compiler/main.ts ===
|
||||
type T1 = typeof import('./input.js').myFunction;
|
||||
>T1 : Symbol(T1, Decl(main.ts, 0, 0))
|
||||
>myFunction : Symbol(myFunction, Decl(input.ts, 8, 1))
|
||||
|
||||
type T2 = typeof import('./input.js').myFunction<any, { slug: 'hello' }>;
|
||||
>T2 : Symbol(T2, Decl(main.ts, 0, 49))
|
||||
>myFunction : Symbol(myFunction, Decl(input.ts, 8, 1))
|
||||
>slug : Symbol(slug, Decl(main.ts, 1, 55))
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
=== tests/cases/compiler/input.ts ===
|
||||
// @strict
|
||||
|
||||
// Repro from #52248
|
||||
|
||||
interface Arg<T = any, Params extends Record<string, any> = Record<string, any>> {
|
||||
"__is_argument__"?: true;
|
||||
>"__is_argument__" : true
|
||||
>true : true
|
||||
|
||||
meta?: T;
|
||||
>meta : T
|
||||
|
||||
params?: Params;
|
||||
>params : Params
|
||||
}
|
||||
|
||||
export function myFunction<T = any, U extends Record<string, any> = Record<string, any>>(arg: Arg<T, U>) { return (arg.params || {}) as U }
|
||||
>myFunction : <T = any, U extends Record<string, any> = Record<string, any>>(arg: Arg<T, U>) => U
|
||||
>arg : Arg<T, U>
|
||||
>(arg.params || {}) as U : U
|
||||
>(arg.params || {}) : U | {}
|
||||
>arg.params || {} : U | {}
|
||||
>arg.params : U
|
||||
>arg : Arg<T, U>
|
||||
>params : U
|
||||
>{} : {}
|
||||
|
||||
=== tests/cases/compiler/main.ts ===
|
||||
type T1 = typeof import('./input.js').myFunction;
|
||||
>T1 : <T = any, U extends Record<string, any> = Record<string, any>>(arg: Arg<T, U>) => U
|
||||
>myFunction : error
|
||||
|
||||
type T2 = typeof import('./input.js').myFunction<any, { slug: 'hello' }>;
|
||||
>T2 : (arg: Arg<any, { slug: 'hello'; }>) => { slug: 'hello'; }
|
||||
>myFunction : error
|
||||
>slug : "hello"
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// @strict
|
||||
|
||||
// Repro from #52248
|
||||
|
||||
// @filename: input.ts
|
||||
interface Arg<T = any, Params extends Record<string, any> = Record<string, any>> {
|
||||
"__is_argument__"?: true;
|
||||
meta?: T;
|
||||
params?: Params;
|
||||
}
|
||||
|
||||
export function myFunction<T = any, U extends Record<string, any> = Record<string, any>>(arg: Arg<T, U>) { return (arg.params || {}) as U }
|
||||
|
||||
// @filename: main.ts
|
||||
type T1 = typeof import('./input.js').myFunction;
|
||||
type T2 = typeof import('./input.js').myFunction<any, { slug: 'hello' }>;
|
Загрузка…
Ссылка в новой задаче