TypeScript - как запретить взаимозаменяемому использованию двух псевдонимов типа, которые разрешаются в один и тот же тип? - PullRequest
1 голос
/ 05 мая 2020

Допустим, у меня есть два или более псевдонима типов, как таковых:

declare type A = string;
declare type B = string;

У меня есть переменные этих типов, а также функции, которые с ними работают.

const a1: A = "example of a";
const b1: B = "example of b";

function withA(a: A){
    console.log(a);
}

function withB(b: B){
    console.log(b);
}

Я хотел бы, чтобы следующий код вызывал ошибку, но это не так:

withA(b1);
withB(a1);

Как я могу выполнить sh это? Мне также нужно будет иметь возможность инициализировать переменные строкой (я предполагаю, что это приведение). Однако после инициализации я не хочу, чтобы типы были «неявно эквивалентными», и хочу, чтобы компилятор запретил их взаимозаменяемое использование.

Я также не хотел бы использовать классы, как описано здесь: TypeScript - указывает c типы строк

1 Ответ

3 голосов
/ 05 мая 2020

Псевдонимы типов, как следует из их названия, ничего не добавляют к типу, который они псевдонимы. Что касается TS, то и A, и B относятся к одному и тому же типу, а именно string.

Что вы можете сделать, так это использовать фирменные типы. Это метод, при котором вы берете базовый тип (в данном случае string) и пересекаете его с типом объекта со свойством, чтобы сделать этот тип структурно несовместимым с чем-либо еще с точки зрения компилятора. Свойство не обязательно должно существовать во время выполнения, оно просто используется как маркер для компилятора:

type A = string & { __brand: "A"};
type B = string & { __brand: "B"};

const a1: A = makeA("example of a");
const b1: B =  makeB("example of b");

function makeA(s: string) {
    return s as A
}
function makeB(s: string) {
    return s as B
}
function withA(a: A){
    console.log(a);
}

function withB(b: B){
    console.log(b);
}

withA(b1); // error
withB(a1); // error

Вспомогательные функции makeA и makeB не являются строго обязательными, вы можете просто использовать Утверждение типа, когда вы назначаете string, но они улучшают DX.

Примечание : есть два предложения по формализации этого метода в системе типов ( Structural tag type бренды и номинал unique type бренды ), но ни один из них не объединен на момент написания, возможно, в будущей версии TS мы получим один из них.

...