定义一个无法自动转换为别名的类型

时间:2017-08-22 09:32:33

标签: typescript

是否可以在TypeScript中定义一个不会自动推断为别名的类型?

type id = string;
type int = number;

如果没有明确指定为声明的类型,那么我想得到一个错误:

function foo(id: id) {}

var s:string = "123";
foo(s); // error?

我希望foo("123")也是一个错误,除非你投了它:foo("123" as id)

2 个答案:

答案 0 :(得分:1)

认为这是不可能的,因为TS使用结构而非名义输入。您可以在此处找到更多信息:

https://www.typescriptlang.org/docs/handbook/type-compatibility.html

猜猜你是否需要这个功能,你必须切换到flow-type。他们得到了这个:https://flow.org/en/docs/types/opaque-types/

编辑:猜猜这是TS团队的计划:Microsoft/TypeScript#5228

答案 1 :(得分:1)

在TypeScript中获取此行为的主要方法是一种名为"branding"的技术(另请参阅Microsoft/Typescript#4895中的讨论)。我们的想法是,您使用没有运行时效果的“品牌”来扩充基本类型,但这会使类型系统将其与基本类型区分开来。

对于您的情况,我们可以这样做:

type id = string & { __brand: 'id' };
type int = number & { __brand: 'int' };

function foo(id: id) {}

var s:string = "123";
foo(s); // error
foo("123"); // error
foo("123" as id) //okay

正如您所看到的,它的行为或多或少完全符合您的要求。请注意,它仍然认为品牌类型与基本类型兼容,因此您可以这样做:

const i: int = 5 as int;
const j: number = i; // that's okay, an int is a number

这种技术的主要缺点是你基本上对类型系统说谎:__brandstring没有number属性。但如果品牌是good enough for the compiler itself,那对我们来说可能已经足够了。

还有其他方法可以进行品牌/标记,但这应该适合您。祝你好运!