тип экспорта машинописного текста и значение модуля - PullRequest
1 голос
/ 06 апреля 2020

Я хочу экспортировать тип с тем же именем, что и значение. Вот пример модуля:

// foo.ts

export type Foo = string;

export function create(): Foo {
  // ...
}

По какой причине этот шаблон работает:

// index.ts
import * as _Foo from "./foo";
export const Foo = _Foo;
export type Foo = _Foo.Foo;

Но эти шаблоны не работают?

// No compiler error but value is not exported
export type Foo = import("./foo").Foo;
export * as Foo from "./foo";

// Duplicate identifier error
import type { Foo } from "./foo";
import * as Foo from "./foo";
export { Foo };

// Individual declarations in merged declaration 'Point' must be all exported or all local. [2395]
import * as Foo from "./foo";
export { Foo };
export type Foo = Foo.Foo;

1 Ответ

0 голосов
/ 07 апреля 2020

Псевдонимы типа не дают значения .

Позвольте мне объяснить, что происходит в ваших примерах

// Types (Foo) and values (create) are imported into a single variable
import * as _Foo from "./foo"; 

// The module is reexported with another name
export const Foo = _Foo;

// The type is reexported with another name
export type Foo = _Foo.Foo;

Скомпилированная версия не содержит тип курс

var _Foo = require("./foo");
exports.Foo = _Foo;

После этого, если Foo используется как тип, он правильно разрешается в string, но если Foo используется в качестве значения, это объект с полем create .

Забавно, что вы можете использовать typeof Foo сейчас, и это будет { create: () => string }

Движение вперед. Следующее почти такое же, как и в предыдущем случае, но поскольку первый импорт явно заявляет это это тип, который можно использовать с тем же именем для экспорта значения

export type Foo = import("./foo").Foo; // does not produce a variable
export * as Foo from "./foo"; // named value export

Компилируется в

exports.Foo = require("./foo");

Следующий немного сложнее, если честно, я не Не знаю, почему это не работает. Я предполагаю, что это может быть ошибкой, поскольку import type - блестящая новая функция, но я не нашел ее.

import type { Foo } from "./foo";
import * as Foo from "./foo";
export { Foo };

Работает локально определенный тип:

type Foo = string;
import * as Foo from "./foo";
export { Foo };

И последняя , поскольку в этом импорте объявлено Foo, его нельзя объединить. Вы можете посмотреть эту проблему для подробностей.

import * as Foo from "./foo";
export { Foo }; 
export type Foo = Foo.Foo; // <- local definition

Его можно переписать, используя временный идентификатор, просто вы сделали это в первом примере: (это не работает, см. обновление ниже)

import * as _Foo from './Foo'
export { _Foo as Foo }
export type Foo = _Foo.Foo

Обновление

Последний приведенный фрагмент дает правильный js вывод, но выдает ошибку, когда экспорт используется в качестве значения:

import * as _Foo from './merged'
const x: Foo = '1234'; // Ok
const y = Foo.create(); // <- TS2693: 'Foo' only refers to a type, but is being used as a value here.

Это похоже на ошибку, но я не могу найти ее опубликованной

...