TypeScript鸭打字,想要强静态打字

TypeScript Duck Typing, Want Strong Static Typing

TypeScript使用编译时(静态)鸭子类型。

我喜欢扩展基本类型以防止错误替换。例如,我想给信用卡号变量赋予信用卡号类型,而不是整数。我最近尝试在TypeScript中使用一对扩展String的接口进行此操作,结果发现它们可以自由地相互替代(并且该字符串可以同时替代两者)。

我真的很想获得编译时标称输入。有什么想法吗?


我想出了一种增强打字强度的方法。我不太喜欢。一个会在每种类型上添加一个特殊的字段或方法,这将使其与其他类型不兼容,而这些类型可能会混淆为鸭子。

以下内容不允许用Parrot代替Duck,因为Duck类具有其他方法(因此Parrot无法进行Duck键入)。麻雀和鹦鹉显然可以代替鸭子,因为鹦鹉无法做麻雀不能做的事,反之亦然。当然,鸭子可以代替鹦鹉,因为如果听起来像鹦鹉,那它就是鹦鹉。

使用www.typescriptlang.org/Playground/进行测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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中有效,但在操场上不可用):

1
2
3
4
5
6
7
8
9
10
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中的原子类型区分(标称原子类型)

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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