fix(55994): Type-check Import Attributes in static imports (#56034)

This commit is contained in:
Oleksandr T 2024-01-11 01:35:04 +02:00 committed by GitHub
parent 9999f26483
commit 72d497352f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 678 additions and 4 deletions

View File

@ -325,6 +325,7 @@ import {
getModeForUsageLocation,
getModifiers,
getModuleInstanceState,
getNameFromImportAttribute,
getNameFromIndexInfo,
getNameOfDeclaration,
getNameOfExpando,
@ -407,6 +408,7 @@ import {
IdentifierTypePredicate,
idText,
IfStatement,
ImportAttribute,
ImportAttributes,
ImportCall,
ImportClause,
@ -553,6 +555,7 @@ import {
isIdentifierTypePredicate,
isIdentifierTypeReference,
isIfStatement,
isImportAttributes,
isImportCall,
isImportClause,
isImportDeclaration,
@ -2179,6 +2182,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
var deferredGlobalImportMetaType: ObjectType;
var deferredGlobalImportMetaExpressionType: ObjectType;
var deferredGlobalImportCallOptionsType: ObjectType | undefined;
var deferredGlobalImportAttributesType: ObjectType | undefined;
var deferredGlobalDisposableType: ObjectType | undefined;
var deferredGlobalAsyncDisposableType: ObjectType | undefined;
var deferredGlobalExtractSymbol: Symbol | undefined;
@ -11555,6 +11559,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true, CheckMode.Normal), declaration, reportErrors);
}
function getTypeFromImportAttributes(node: ImportAttributes): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
const symbol = createSymbol(SymbolFlags.ObjectLiteral, InternalSymbolName.ImportAttributes);
const members = createSymbolTable();
forEach(node.elements, attr => {
const member = createSymbol(SymbolFlags.Property, getNameFromImportAttribute(attr));
member.parent = symbol;
member.links.type = checkImportAttribute(attr);
member.links.target = member;
members.set(member.escapedName, member);
});
const type = createAnonymousType(symbol, members, emptyArray, emptyArray, emptyArray);
type.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.NonInferrableType;
links.resolvedType = type;
}
return links.resolvedType;
}
function isGlobalSymbolConstructor(node: Node) {
const symbol = getSymbolOfNode(node);
const globalSymbol = getGlobalESSymbolConstructorTypeSymbol(/*reportErrors*/ false);
@ -16417,6 +16440,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return (deferredGlobalImportCallOptionsType ||= getGlobalType("ImportCallOptions" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
}
function getGlobalImportAttributesType(reportErrors: boolean) {
return (deferredGlobalImportAttributesType ||= getGlobalType("ImportAttributes" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
}
function getGlobalESSymbolConstructorSymbol(reportErrors: boolean): Symbol | undefined {
return deferredGlobalESSymbolConstructorSymbol ||= getGlobalValueSymbol("Symbol" as __String, reportErrors);
}
@ -30904,6 +30931,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxSelfClosingElement:
return getContextualJsxElementAttributesType(parent as JsxOpeningLikeElement, contextFlags);
case SyntaxKind.ImportAttribute:
return getContextualImportAttributeType(parent as ImportAttribute);
}
return undefined;
}
@ -30950,6 +30979,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
function getContextualImportAttributeType(node: ImportAttribute) {
return getTypeOfPropertyOfContextualType(getGlobalImportAttributesType(/*reportErrors*/ false), getNameFromImportAttribute(node));
}
function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement, contextFlags: ContextFlags | undefined) {
if (isJsxOpeningElement(node) && contextFlags !== ContextFlags.Completions) {
const index = findContextualNode(node.parent, /*includeCaches*/ !contextFlags);
@ -45991,6 +46024,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
function checkImportAttributes(declaration: ImportDeclaration | ExportDeclaration) {
const node = declaration.attributes;
if (node) {
const importAttributesType = getGlobalImportAttributesType(/*reportErrors*/ true);
if (importAttributesType !== emptyObjectType) {
checkTypeAssignableTo(getTypeFromImportAttributes(node), getNullableType(importAttributesType, TypeFlags.Undefined), node);
}
const validForTypeAttributes = isExclusivelyTypeOnlyImportOrExport(declaration);
const override = getResolutionModeOverride(node, validForTypeAttributes ? grammarErrorOnNode : undefined);
const isImportAttributes = declaration.attributes.token === SyntaxKind.WithKeyword;
@ -46020,6 +46058,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
function checkImportAttribute(node: ImportAttribute) {
return getRegularTypeOfLiteralType(checkExpressionCached(node.value));
}
function checkImportDeclaration(node: ImportDeclaration) {
if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) {
// If we hit an import declaration in an illegal context, just bail out to avoid cascading errors.
@ -47700,6 +47742,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return checkMetaPropertyKeyword(node.parent);
}
if (isImportAttributes(node)) {
return getGlobalImportAttributesType(/*reportErrors*/ false);
}
return errorType;
}

View File

@ -5971,6 +5971,7 @@ export const enum InternalSymbolName {
Default = "default", // Default export symbol (technically not wholly internal, but included here for usability)
This = "this",
InstantiationExpression = "__instantiationExpression", // Instantiation expressions
ImportAttributes = "__importAttributes",
}
/**

View File

@ -220,6 +220,7 @@ import {
idText,
IfStatement,
ignoredPaths,
ImportAttribute,
ImportCall,
ImportClause,
ImportDeclaration,
@ -10656,3 +10657,8 @@ export function replaceFirstStar(s: string, replacement: string): string {
// Attempt to defeat this analysis by indirectly calling the method.
return stringReplace.call(s, "*", replacement);
}
/** @internal */
export function getNameFromImportAttribute(node: ImportAttribute) {
return isIdentifier(node.name) ? node.name.escapedText : escapeLeadingUnderscores(node.name.text);
}

View File

@ -2448,7 +2448,13 @@ export class TestState {
const annotations = this.annotateContentWithTooltips(
result,
"completions",
item => item.optionalReplacementSpan,
item => {
if (item.optionalReplacementSpan) {
const { start, length } = item.optionalReplacementSpan;
return start && length === 0 ? { start, length: 1 } : item.optionalReplacementSpan;
}
return undefined;
},
item =>
item.entries?.flatMap(
entry =>

View File

@ -95,6 +95,7 @@ import {
getLineStartPositionForPosition,
getLocalSymbolForExportDefault,
getModifiers,
getNameFromImportAttribute,
getNameOfDeclaration,
getNameTable,
getNewLineCharacter,
@ -169,6 +170,7 @@ import {
isIdentifier,
isIdentifierText,
isImportableFile,
isImportAttributes,
isImportDeclaration,
isImportEqualsDeclaration,
isImportKeyword,
@ -3768,6 +3770,7 @@ function getCompletionData(
|| tryGetObjectLikeCompletionSymbols()
|| tryGetImportCompletionSymbols()
|| tryGetImportOrExportClauseCompletionSymbols()
|| tryGetImportAttributesCompletionSymbols()
|| tryGetLocalNamedExportCompletionSymbols()
|| tryGetConstructorCompletion()
|| tryGetClassLikeCompletionSymbols()
@ -4455,6 +4458,21 @@ function getCompletionData(
return GlobalsSearch.Success;
}
/**
* import { x } from "foo" with { | }
*/
function tryGetImportAttributesCompletionSymbols(): GlobalsSearch {
if (contextToken === undefined) return GlobalsSearch.Continue;
const importAttributes = contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken ? tryCast(contextToken.parent, isImportAttributes) :
contextToken.kind === SyntaxKind.ColonToken ? tryCast(contextToken.parent.parent, isImportAttributes) : undefined;
if (importAttributes === undefined) return GlobalsSearch.Continue;
const existing = new Set(importAttributes.elements.map(getNameFromImportAttribute));
symbols = filter(typeChecker.getTypeAtLocation(importAttributes).getApparentProperties(), attr => !existing.has(attr.escapedName));
return GlobalsSearch.Success;
}
/**
* Adds local declarations for completions in named exports:
*

View File

@ -7076,6 +7076,7 @@ declare namespace ts {
Default = "default",
This = "this",
InstantiationExpression = "__instantiationExpression",
ImportAttributes = "__importAttributes",
}
/**
* This represents a string whose leading underscore have been escaped by adding extra leading underscores.

View File

@ -0,0 +1,334 @@
// === Completions ===
=== /tests/cases/fourslash/./b.ts ===
// declare global {
// interface ImportAttributes {
// type: "json",
// "resolution-mode": "import"
// }
// }
// const str = "hello";
//
// import * as t1 from "./a" with { };
// ^
// | ----------------------------------------------------------------------
// | (property) ImportAttributes["resolution-mode"]: "import"
// | (property) ImportAttributes.type: "json"
// | ----------------------------------------------------------------------
// import * as t2 from "./a" with { type: "" };
// ^
// | ----------------------------------------------------------------------
// | json
// | ----------------------------------------------------------------------
// import * as t3 from "./a" with { type: "json", };
// ^
// | ----------------------------------------------------------------------
// | (property) ImportAttributes["resolution-mode"]: "import"
// | ----------------------------------------------------------------------
// import * as t4 from "./a" with { type: };
// ^
// | ----------------------------------------------------------------------
// | "json"
// | (property) ImportAttributes["resolution-mode"]: "import"
// | ----------------------------------------------------------------------
[
{
"marker": {
"fileName": "/tests/cases/fourslash/./b.ts",
"position": 171,
"name": "1"
},
"item": {
"flags": 0,
"isGlobalCompletion": false,
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
{
"name": "resolution-mode",
"kind": "property",
"kindModifiers": "declare",
"sortText": "11",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "ImportAttributes",
"kind": "interfaceName"
},
{
"text": "[",
"kind": "punctuation"
},
{
"text": "\"resolution-mode\"",
"kind": "stringLiteral"
},
{
"text": "]",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "\"import\"",
"kind": "stringLiteral"
}
],
"documentation": []
},
{
"name": "type",
"kind": "property",
"kindModifiers": "declare",
"sortText": "11",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "ImportAttributes",
"kind": "interfaceName"
},
{
"text": ".",
"kind": "punctuation"
},
{
"text": "type",
"kind": "propertyName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "\"json\"",
"kind": "stringLiteral"
}
],
"documentation": []
}
]
}
},
{
"marker": {
"fileName": "/tests/cases/fourslash/./b.ts",
"position": 215,
"name": "2"
},
"item": {
"isGlobalCompletion": false,
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"optionalReplacementSpan": {
"start": 215,
"length": 0
},
"entries": [
{
"name": "json",
"kindModifiers": "",
"kind": "string",
"sortText": "11",
"replacementSpan": {
"start": 215,
"length": 0
},
"displayParts": [
{
"text": "json",
"kind": "text"
}
]
}
]
}
},
{
"marker": {
"fileName": "/tests/cases/fourslash/./b.ts",
"position": 267,
"name": "3"
},
"item": {
"flags": 0,
"isGlobalCompletion": false,
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
{
"name": "resolution-mode",
"kind": "property",
"kindModifiers": "declare",
"sortText": "11",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "ImportAttributes",
"kind": "interfaceName"
},
{
"text": "[",
"kind": "punctuation"
},
{
"text": "\"resolution-mode\"",
"kind": "stringLiteral"
},
{
"text": "]",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "\"import\"",
"kind": "stringLiteral"
}
],
"documentation": []
}
]
}
},
{
"marker": {
"fileName": "/tests/cases/fourslash/./b.ts",
"position": 310,
"name": "4"
},
"item": {
"flags": 0,
"isGlobalCompletion": false,
"isMemberCompletion": false,
"isNewIdentifierLocation": false,
"entries": [
{
"name": "\"json\"",
"kind": "string",
"kindModifiers": "",
"sortText": "11",
"displayParts": [
{
"text": "\"json\"",
"kind": "stringLiteral"
}
]
},
{
"name": "resolution-mode",
"kind": "property",
"kindModifiers": "declare",
"sortText": "11",
"displayParts": [
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "ImportAttributes",
"kind": "interfaceName"
},
{
"text": "[",
"kind": "punctuation"
},
{
"text": "\"resolution-mode\"",
"kind": "stringLiteral"
},
{
"text": "]",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "\"import\"",
"kind": "stringLiteral"
}
],
"documentation": []
}
]
}
}
]

View File

@ -17,7 +17,7 @@
// createStyles({
// x: {
// '': ''
//
// ^
// | ----------------------------------------------------------------------
// | (property) alignContent?: string
// | (property) alignItems?: string

View File

@ -1,13 +1,29 @@
mod.mts(1,37): error TS2322: Type '{ field: 0; }' is not assignable to type 'ImportAttributes'.
Property 'field' is incompatible with index signature.
Type 'number' is not assignable to type 'string'.
mod.mts(1,52): error TS2837: Import assertion values must be string literal expressions.
mod.mts(3,52): error TS2837: Import assertion values must be string literal expressions.
mod.mts(5,37): error TS2322: Type '{ field: RegExp; }' is not assignable to type 'ImportAttributes'.
Property 'field' is incompatible with index signature.
Type 'RegExp' is not assignable to type 'string'.
mod.mts(5,52): error TS2837: Import assertion values must be string literal expressions.
mod.mts(7,37): error TS2322: Type '{ field: string[]; }' is not assignable to type 'ImportAttributes'.
Property 'field' is incompatible with index signature.
Type 'string[]' is not assignable to type 'string'.
mod.mts(7,52): error TS2837: Import assertion values must be string literal expressions.
mod.mts(9,37): error TS2322: Type '{ field: { a: number; }; }' is not assignable to type 'ImportAttributes'.
Property 'field' is incompatible with index signature.
Type '{ a: number; }' is not assignable to type 'string'.
mod.mts(9,52): error TS2837: Import assertion values must be string literal expressions.
mod.mts(11,66): error TS2837: Import assertion values must be string literal expressions.
==== mod.mts (6 errors) ====
==== mod.mts (10 errors) ====
import * as thing1 from "./mod.mjs" assert {field: 0};
~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ field: 0; }' is not assignable to type 'ImportAttributes'.
!!! error TS2322: Property 'field' is incompatible with index signature.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
~
!!! error TS2837: Import assertion values must be string literal expressions.
@ -16,14 +32,26 @@ mod.mts(11,66): error TS2837: Import assertion values must be string literal exp
!!! error TS2837: Import assertion values must be string literal expressions.
import * as thing3 from "./mod.mjs" assert {field: /a/g};
~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ field: RegExp; }' is not assignable to type 'ImportAttributes'.
!!! error TS2322: Property 'field' is incompatible with index signature.
!!! error TS2322: Type 'RegExp' is not assignable to type 'string'.
~~~~
!!! error TS2837: Import assertion values must be string literal expressions.
import * as thing4 from "./mod.mjs" assert {field: ["a"]};
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ field: string[]; }' is not assignable to type 'ImportAttributes'.
!!! error TS2322: Property 'field' is incompatible with index signature.
!!! error TS2322: Type 'string[]' is not assignable to type 'string'.
~~~~~
!!! error TS2837: Import assertion values must be string literal expressions.
import * as thing5 from "./mod.mjs" assert {field: { a: 0 }};
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ field: { a: number; }; }' is not assignable to type 'ImportAttributes'.
!!! error TS2322: Property 'field' is incompatible with index signature.
!!! error TS2322: Type '{ a: number; }' is not assignable to type 'string'.
~~~~~~~~
!!! error TS2837: Import assertion values must be string literal expressions.

View File

@ -1,25 +1,53 @@
mod.mts(1,37): error TS2322: Type '{ field: 0; }' is not assignable to type 'ImportAttributes'.
Property 'field' is incompatible with index signature.
Type 'number' is not assignable to type 'string'.
mod.mts(1,51): error TS2858: Import attribute values must be string literal expressions.
mod.mts(2,51): error TS2858: Import attribute values must be string literal expressions.
mod.mts(3,37): error TS2322: Type '{ field: RegExp; }' is not assignable to type 'ImportAttributes'.
Property 'field' is incompatible with index signature.
Type 'RegExp' is not assignable to type 'string'.
mod.mts(3,51): error TS2858: Import attribute values must be string literal expressions.
mod.mts(4,37): error TS2322: Type '{ field: string[]; }' is not assignable to type 'ImportAttributes'.
Property 'field' is incompatible with index signature.
Type 'string[]' is not assignable to type 'string'.
mod.mts(4,51): error TS2858: Import attribute values must be string literal expressions.
mod.mts(5,37): error TS2322: Type '{ field: { a: number; }; }' is not assignable to type 'ImportAttributes'.
Property 'field' is incompatible with index signature.
Type '{ a: number; }' is not assignable to type 'string'.
mod.mts(5,51): error TS2858: Import attribute values must be string literal expressions.
mod.mts(6,65): error TS2858: Import attribute values must be string literal expressions.
==== mod.mts (6 errors) ====
==== mod.mts (10 errors) ====
import * as thing1 from "./mod.mjs" with { field: 0 };
~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ field: 0; }' is not assignable to type 'ImportAttributes'.
!!! error TS2322: Property 'field' is incompatible with index signature.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
~
!!! error TS2858: Import attribute values must be string literal expressions.
import * as thing2 from "./mod.mjs" with { field: `a` };
~~~
!!! error TS2858: Import attribute values must be string literal expressions.
import * as thing3 from "./mod.mjs" with { field: /a/g };
~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ field: RegExp; }' is not assignable to type 'ImportAttributes'.
!!! error TS2322: Property 'field' is incompatible with index signature.
!!! error TS2322: Type 'RegExp' is not assignable to type 'string'.
~~~~
!!! error TS2858: Import attribute values must be string literal expressions.
import * as thing4 from "./mod.mjs" with { field: ["a"] };
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ field: string[]; }' is not assignable to type 'ImportAttributes'.
!!! error TS2322: Property 'field' is incompatible with index signature.
!!! error TS2322: Type 'string[]' is not assignable to type 'string'.
~~~~~
!!! error TS2858: Import attribute values must be string literal expressions.
import * as thing5 from "./mod.mjs" with { field: { a: 0 } };
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ field: { a: number; }; }' is not assignable to type 'ImportAttributes'.
!!! error TS2322: Property 'field' is incompatible with index signature.
!!! error TS2322: Type '{ a: number; }' is not assignable to type 'string'.
~~~~~~~~
!!! error TS2858: Import attribute values must be string literal expressions.
import * as thing6 from "./mod.mjs" with { type: "json", field: 0..toString() };

View File

@ -0,0 +1,41 @@
b.ts(7,27): error TS2322: Type '{ type: "not-json"; }' is not assignable to type 'ImportAttributes'.
Types of property 'type' are incompatible.
Type '"not-json"' is not assignable to type '"json"'.
b.ts(11,25): error TS2322: Type '{ with: { type: "not-json"; }; }' is not assignable to type 'ImportCallOptions'.
The types of 'with.type' are incompatible between these types.
Type '"not-json"' is not assignable to type '"json"'.
==== ./a.ts (0 errors) ====
export default {};
==== ./b.ts (2 errors) ====
declare global {
interface ImportAttributes {
type: "json"
}
}
import * as ns from "./a" with { type: "not-json" };
~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ type: "not-json"; }' is not assignable to type 'ImportAttributes'.
!!! error TS2322: Types of property 'type' are incompatible.
!!! error TS2322: Type '"not-json"' is not assignable to type '"json"'.
void ns;
async function f() {
await import("./a", {
~
with: {
~~~~~~~~~~~~~~~
type: "not-json",
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
},
~~~~~~~~~~
});
~~~~~
!!! error TS2322: Type '{ with: { type: "not-json"; }; }' is not assignable to type 'ImportCallOptions'.
!!! error TS2322: The types of 'with.type' are incompatible between these types.
!!! error TS2322: Type '"not-json"' is not assignable to type '"json"'.
}

View File

@ -0,0 +1,36 @@
//// [tests/cases/conformance/importAttributes/importAttributes9.ts] ////
//// [a.ts]
export default {};
//// [b.ts]
declare global {
interface ImportAttributes {
type: "json"
}
}
import * as ns from "./a" with { type: "not-json" };
void ns;
async function f() {
await import("./a", {
with: {
type: "not-json",
},
});
}
//// [a.js]
export default {};
//// [b.js]
import * as ns from "./a" with { type: "not-json" };
void ns;
async function f() {
await import("./a", {
with: {
type: "not-json",
},
});
}

View File

@ -0,0 +1,40 @@
//// [tests/cases/conformance/importAttributes/importAttributes9.ts] ////
=== ./a.ts ===
export default {};
=== ./b.ts ===
declare global {
>global : Symbol(global, Decl(b.ts, 0, 0))
interface ImportAttributes {
>ImportAttributes : Symbol(ImportAttributes, Decl(lib.es5.d.ts, --, --), Decl(b.ts, 0, 16))
type: "json"
>type : Symbol(ImportAttributes.type, Decl(b.ts, 1, 33))
}
}
import * as ns from "./a" with { type: "not-json" };
>ns : Symbol(ns, Decl(b.ts, 6, 6))
void ns;
>ns : Symbol(ns, Decl(b.ts, 6, 6))
async function f() {
>f : Symbol(f, Decl(b.ts, 7, 8))
await import("./a", {
>"./a" : Symbol(ns, Decl(a.ts, 0, 0))
with: {
>with : Symbol(with, Decl(b.ts, 10, 25))
type: "not-json",
>type : Symbol(type, Decl(b.ts, 11, 15))
},
});
}

View File

@ -0,0 +1,45 @@
//// [tests/cases/conformance/importAttributes/importAttributes9.ts] ////
=== ./a.ts ===
export default {};
>{} : {}
=== ./b.ts ===
declare global {
>global : any
interface ImportAttributes {
type: "json"
>type : "json"
}
}
import * as ns from "./a" with { type: "not-json" };
>ns : typeof ns
>type : any
void ns;
>void ns : undefined
>ns : typeof ns
async function f() {
>f : () => Promise<void>
await import("./a", {
>await import("./a", { with: { type: "not-json", }, }) : typeof ns
>import("./a", { with: { type: "not-json", }, }) : Promise<typeof ns>
>"./a" : "./a"
>{ with: { type: "not-json", }, } : { with: { type: "not-json"; }; }
with: {
>with : { type: "not-json"; }
>{ type: "not-json", } : { type: "not-json"; }
type: "not-json",
>type : "not-json"
>"not-json" : "not-json"
},
});
}

View File

@ -0,0 +1,22 @@
// @module: esnext
// @target: esnext
// @filename: ./a.ts
export default {};
// @filename: ./b.ts
declare global {
interface ImportAttributes {
type: "json"
}
}
import * as ns from "./a" with { type: "not-json" };
void ns;
async function f() {
await import("./a", {
with: {
type: "not-json",
},
});
}

View File

@ -0,0 +1,22 @@
///<reference path="fourslash.ts" />
// @module: esnext
// @target: esnext
// @filename: ./a.ts
////export default {};
// @filename: ./b.ts
////declare global {
//// interface ImportAttributes {
//// type: "json",
//// "resolution-mode": "import"
//// }
////}
////const str = "hello";
////
////import * as t1 from "./a" with { /*1*/ };
////import * as t2 from "./a" with { type: "/*2*/" };
////import * as t3 from "./a" with { type: "json", /*3*/ };
////import * as t4 from "./a" with { type: /*4*/ };
verify.baselineCompletions();