mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-07-02 14:48:32 -05:00
Module or import types (#22592)
* Type side of import types * Value side of import types * Accept library changes * Refined implementation, more tests * Allow resolutions to be performed late if the resolution still results in a file already in the build * Add another test case * Add some jsdoc usages * Allow nodebuilder to use import types where appropriate * Parse & check generic instantiations * use import types in nodebuilder for typeof module symbols * Wire up go to definition for import types * Accept updated type/symbol baselines now that symbols are wired in * PR feedback * Fix changes from merge * Walk back late import handling * Remove unused diagnostic * Remove unrelated changes * Use recursive function over loop * Emit type arguments * undo unrelated change * Test for and support import type nodes in bundled declaration emit
This commit is contained in:
42
tests/cases/conformance/types/import/importTypeAmbient.ts
Normal file
42
tests/cases/conformance/types/import/importTypeAmbient.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
// @declaration: true
|
||||
// @lib: es6
|
||||
declare module "foo" {
|
||||
interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
export = Point;
|
||||
}
|
||||
const x: import("foo") = { x: 0, y: 0 };
|
||||
|
||||
declare module "foo2" {
|
||||
namespace Bar {
|
||||
interface I {
|
||||
a: string;
|
||||
b: number;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Baz {
|
||||
interface J {
|
||||
a: number;
|
||||
b: string;
|
||||
}
|
||||
}
|
||||
|
||||
class Bar {
|
||||
item: Bar.I;
|
||||
constructor(input: Baz.J);
|
||||
}
|
||||
}
|
||||
|
||||
let y: import("foo2").Bar.I = { a: "", b: 0 };
|
||||
|
||||
class Bar2 {
|
||||
item: {a: string, b: number, c: object};
|
||||
constructor(input?: any) {}
|
||||
}
|
||||
|
||||
let shim: typeof import("foo2") = {
|
||||
Bar: Bar2
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
// @declaration: true
|
||||
// @lib: es6
|
||||
declare module "foo" {
|
||||
interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
export = Point;
|
||||
}
|
||||
const x: import("fo") = { x: 0, y: 0 }; // typo, error
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// @declaration: true
|
||||
// @module: amd
|
||||
// @outFile: bundle.js
|
||||
// @filename: a/b/c.ts
|
||||
export interface Foo {
|
||||
x: 12;
|
||||
}
|
||||
// @filename: a/inner.ts
|
||||
const c: import("./b/c").Foo = {x: 12};
|
||||
export {c};
|
||||
|
||||
// @filename: index.ts
|
||||
const d: typeof import("./a/inner")["c"] = {x: 12};
|
||||
export {d};
|
||||
18
tests/cases/conformance/types/import/importTypeGeneric.ts
Normal file
18
tests/cases/conformance/types/import/importTypeGeneric.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// @declaration: true
|
||||
// @target: es6
|
||||
// @filename: a.d.ts
|
||||
export interface Foo {
|
||||
a: string;
|
||||
}
|
||||
// @filename: b.d.ts
|
||||
export interface Foo {
|
||||
a: number;
|
||||
}
|
||||
// @filename: usage.ts
|
||||
export function getFooFrom<T extends "./a" | "./b">(v: T): import(T).Foo {
|
||||
return undefined as any;
|
||||
}
|
||||
|
||||
export function getFooValueFrom<T extends "./a" | "./b">(v: T): import(T).Foo["a"] {
|
||||
return undefined as any;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// @declaration: true
|
||||
// @lib: es6
|
||||
// @filename: foo.ts
|
||||
interface Point<T> {
|
||||
x: number;
|
||||
y: number;
|
||||
data: T;
|
||||
}
|
||||
export = Point;
|
||||
|
||||
// @filename: foo2.ts
|
||||
namespace Bar {
|
||||
export interface I<T> {
|
||||
a: string;
|
||||
b: number;
|
||||
data: T;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Baz {
|
||||
export interface J<T> {
|
||||
a: number;
|
||||
b: string;
|
||||
data: T;
|
||||
}
|
||||
}
|
||||
|
||||
class Bar<T> {
|
||||
item: Bar.I<T>;
|
||||
constructor(input: Baz.J<T>) {}
|
||||
}
|
||||
export { Bar }
|
||||
|
||||
// @filename: usage.ts
|
||||
export const x: import("./foo")<{x: number}> = { x: 0, y: 0, data: {x: 12} };
|
||||
export let y: import("./foo2").Bar.I<{x: number}> = { a: "", b: 0, data: {x: 12} };
|
||||
|
||||
export class Bar2<T> {
|
||||
item: {a: string, b: number, c: object, data: T};
|
||||
constructor(input?: any) {}
|
||||
}
|
||||
|
||||
export let shim: typeof import("./foo2") = {
|
||||
Bar: Bar2
|
||||
};
|
||||
29
tests/cases/conformance/types/import/importTypeInJSDoc.ts
Normal file
29
tests/cases/conformance/types/import/importTypeInJSDoc.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
// @target: es6
|
||||
// @outDir: ./out
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @filename: externs.d.ts
|
||||
declare namespace MyClass {
|
||||
export interface Bar {
|
||||
doer: (x: string) => void;
|
||||
}
|
||||
}
|
||||
declare class MyClass {
|
||||
field: string;
|
||||
static Bar: (x: string, y?: number) => void;
|
||||
constructor(x: MyClass.Bar);
|
||||
}
|
||||
declare global {
|
||||
const Foo: typeof MyClass;
|
||||
}
|
||||
export = MyClass;
|
||||
// @filename: index.js
|
||||
|
||||
/**
|
||||
* @typedef {import("./externs")} Foo
|
||||
*/
|
||||
|
||||
let a = /** @type {Foo} */(/** @type {*} */(undefined));
|
||||
a = new Foo({doer: Foo.Bar});
|
||||
const q = /** @type {import("./externs").Bar} */({ doer: q => q });
|
||||
const r = /** @type {typeof import("./externs").Bar} */(r => r);
|
||||
42
tests/cases/conformance/types/import/importTypeLocal.ts
Normal file
42
tests/cases/conformance/types/import/importTypeLocal.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
// @declaration: true
|
||||
// @lib: es6
|
||||
// @filename: foo.ts
|
||||
interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
export = Point;
|
||||
|
||||
// @filename: foo2.ts
|
||||
namespace Bar {
|
||||
export interface I {
|
||||
a: string;
|
||||
b: number;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Baz {
|
||||
export interface J {
|
||||
a: number;
|
||||
b: string;
|
||||
}
|
||||
}
|
||||
|
||||
class Bar {
|
||||
item: Bar.I;
|
||||
constructor(input: Baz.J) {}
|
||||
}
|
||||
export { Bar }
|
||||
|
||||
// @filename: usage.ts
|
||||
export const x: import("./foo") = { x: 0, y: 0 };
|
||||
export let y: import("./foo2").Bar.I = { a: "", b: 0 };
|
||||
|
||||
export class Bar2 {
|
||||
item: {a: string, b: number, c: object};
|
||||
constructor(input?: any) {}
|
||||
}
|
||||
|
||||
export let shim: typeof import("./foo2") = {
|
||||
Bar: Bar2
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
// @declaration: true
|
||||
// @lib: es6
|
||||
// @filename: foo.ts
|
||||
interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
export = Point;
|
||||
|
||||
// @filename: foo2.ts
|
||||
namespace Bar {
|
||||
export interface I {
|
||||
a: string;
|
||||
b: number;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Baz {
|
||||
export interface J {
|
||||
a: number;
|
||||
b: string;
|
||||
}
|
||||
}
|
||||
|
||||
class Bar {
|
||||
item: Bar.I;
|
||||
constructor(input: Baz.J) {}
|
||||
}
|
||||
export { Bar }
|
||||
|
||||
// @filename: usage.ts
|
||||
export const x: import("./fo") = { x: 0, y: 0 };
|
||||
export let y: import("./fo2").Bar.I = { a: "", b: 0 };
|
||||
export let z: import("./foo2").Bar.Q = { a: "", b: 0 };
|
||||
|
||||
export class Bar2 {
|
||||
item: {a: string, b: number, c: object};
|
||||
constructor(input?: any) {}
|
||||
}
|
||||
|
||||
export let shim: typeof import("./fo2") = {
|
||||
Bar: Bar2
|
||||
};
|
||||
8
tests/cases/conformance/types/import/importTypeNested.ts
Normal file
8
tests/cases/conformance/types/import/importTypeNested.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
// @declaration: true
|
||||
// @target: es6
|
||||
// @filename: a.d.ts
|
||||
export type LookAt = "./b";
|
||||
// @filename: b.d.ts
|
||||
export type Value = "yes";
|
||||
// @filename: chainer.ts
|
||||
export const x: import(import("./a").LookAt).Value = "yes";
|
||||
@@ -0,0 +1,9 @@
|
||||
// @declaration: true
|
||||
// @target: es6
|
||||
// @noImplicitReferences: true
|
||||
// @filename: a.d.ts
|
||||
export type LookAt = "./b";
|
||||
// @filename: b.d.ts
|
||||
export type Value = "yes";
|
||||
// @filename: chainer.ts
|
||||
export const x: import(import("./a").LookAt).Value = "yes"; // expect outter import to fail, since b.d.ts isn't in the build
|
||||
@@ -0,0 +1,3 @@
|
||||
// @declaration: true
|
||||
// @target: es6
|
||||
export const x: import({x: 12}) = undefined as any;
|
||||
22
tests/cases/fourslash/importTypeNodeGoToDefinition.ts
Normal file
22
tests/cases/fourslash/importTypeNodeGoToDefinition.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @Filename: /ns.ts
|
||||
/////*refFile*/export namespace /*refFoo*/Foo {
|
||||
//// export namespace /*refBar*/Bar {
|
||||
//// export class /*refBaz*/Baz {}
|
||||
//// }
|
||||
////}
|
||||
|
||||
// @Filename: /usage.ts
|
||||
////type A = typeof import([|/*1*/"./ns"|]).[|/*2*/Foo|].[|/*3*/Bar|];
|
||||
////type B = import([|/*4*/"./ns"|]).[|/*5*/Foo|].[|/*6*/Bar|].[|/*7*/Baz|];
|
||||
|
||||
verify.goToDefinition([
|
||||
["1", "refFile"],
|
||||
["2", "refFoo"],
|
||||
["3", "refBar"],
|
||||
["4", "refFile"],
|
||||
["5", "refFoo"],
|
||||
["6", "refBar"],
|
||||
["7", "refBaz"],
|
||||
]);
|
||||
@@ -7,4 +7,4 @@
|
||||
// @Filename: b.js
|
||||
////exports.x = 0;
|
||||
|
||||
verify.quickInfoAt("",'const x: typeof "/tests/cases/fourslash/b"');
|
||||
verify.quickInfoAt("",'const x: typeof import("/tests/cases/fourslash/b")');
|
||||
|
||||
Reference in New Issue
Block a user