TypeScript Duck Typing, хотите сильную статическую печать

TypeScript использует типизированную (статическую) утку.

Я фанат расширения примитивных типов для предотвращения неправильной подстановки. Например, я хотел бы присвоить переменной номера кредитной карты тип номера кредитной карты, а не целое число. Недавно я попытался сделать это в TypeScript с помощью пары интерфейсов, расширяющих String, и обнаружил, что они свободно заменяют друг друга (и эта строка заменяет оба).

Я действительно хотел бы получить время компиляции именной типизации. Есть идеи?

1 ответ

Я придумал один способ набраться сил. Мне это не очень нравится. Каждый добавляет специальное поле или метод к каждому типу, что делает его несовместимым с другими, которые будут путать как утки.

Следующее не разрешает замену Утки Parrot, потому что в классе Duck есть дополнительный метод (поэтому Parrot не может набрать Duck). Воробьи и попугаи, по-видимому, могут быть заменены при наборе утки, потому что попугай не может ничего сделать, чего не может воробей, и наоборот. Конечно, утка может заменить попугая, потому что если это звучит как попугай, это попугай.

Тест с http://www.typescriptlang.org/Playground/:

class Sparrow {
    sound = "cheep";
}
class Parrot {
    sound = "squawk";
}
class Duck {
    sound = "quack";
    swim(){
        alert("Going for a dip!");
    }
}
var parrot: Parrot = new Sparrow(); // substitutes
var sparrow: Sparrow = new Parrot(); // substitutes
var parrotTwo: Parrot = new Duck();
var duck: Duck = new Parrot(); // IDE & compiler error

alert("Parrot says "+parrot.sound+" and sparrow says "+sparrow.sound+", and 2nd parrot says "+parrotTwo.sound);
alert("A duck says "+duck.sound);

На практике я бы сделал это (что работает в моей IDE, но не на игровой площадке):

interface RawUri extends String {
    rawUri;
}

interface EncodedUri extends String {
    encodedUri;
}

var e: EncodedUri = new RawUri(); // IDE & compiler error
var r: RawUri = new EncodedUri(); // IDE & compiler error

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

Пожалуйста, рассмотрите следующий вопрос:

Атомная дискриминация типов (номинальные атомные типы) в TypeScript

Это пример:

export type Kilos<T> = T & { readonly discriminator: unique symbol };
export type Pounds<T> = T & { readonly discriminator: unique symbol };

export interface MetricWeight {
    value: Kilos<number>
}

export interface ImperialWeight {
    value: Pounds<number>
}

const wm: MetricWeight = { value: 0 as Kilos<number> }
const wi: ImperialWeight = { value: 0 as Pounds<number> }

wm.value = wi.value;                  // Gives compiler error
wi.value = wi.value * 2;              // Gives compiler error
wm.value = wi.value * 2;              // Gives compiler error
const we: MetricWeight = { value: 0 } // Gives compiler error
Другие вопросы по тегам