Permit instantiation expressions in `typeof import(...)` (#52532)

This commit is contained in:
Anders Hejlsberg 2023-02-01 09:09:55 -08:00 коммит произвёл GitHub
Родитель 26eced32ed
Коммит d656487fca
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 137 добавлений и 14 удалений

Просмотреть файл

@ -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' }>;