https://mariusschulz.com/blog/const-assertions-in-literal-expressions-in-typescript
这篇文章讲述了 TypeScript 3.4 提供的一个功能 const 断言,这个功能解决了我以前遇到过的一个问题(axios 定义的 method 就是 "GET" | "POST",不知道现在他们改了么)。
这个类型和对象属性字符串类型是对不上的,比如你直接传递 "HTTPMethod.GET",不过常规方法还是要使用枚举来处理这些问题,由于提取精髓,因此略有删减。
TypeScript 对于类型推断有它自己的一套原则,当你定义了一个封装,如下一个场景就能还原这个问题:
function fetchJSON(url: string, method: "GET" | "POST") {
return fetch(url, { method })
.then(response => response.json());
}
const HTTPRequestMethod = {
CONNECT: "CONNECT",
DELETE: "DELETE",
GET: "GET",
HEAD: "HEAD",
OPTIONS: "OPTIONS",
PATCH: "PATCH",
POST: "POST",
PUT: "PUT",
TRACE: "TRACE"
};
如果你使用:
fetchJSON("https://example.com/", HTTPRequestMethod.GET)
.then(data => {
// ...
});
TS编译器检查类型时会报错,原因在于属性的字符串和字符串类型,这是有区别的,要理解这个问题需要去理解 TS 是如何定义字符串的,这里作者写的很长,综合起来就是:
我们可以设想一下,HTTP的规范定义的 Method 有 9 个,如果我们都那样写扩展字符串类型,这个就很脆了。
TS 3.4 给予了一个新功能来处理这个问题:
const HTTPRequestMethod = {
CONNECT: "CONNECT",
DELETE: "DELETE",
GET: "GET",
HEAD: "HEAD",
OPTIONS: "OPTIONS",
PATCH: "PATCH",
POST: "POST",
PUT: "PUT",
TRACE: "TRACE"
} as const;
这是使用 const 关键字的特殊类型:
由于变成了只读,如果你还想给 HTTPRequestMethod 分配新的值时,TS编译器是会给出错误的。
最后结论:
例如,您可以定义一个ORIGIN变量来描述二维空间中的原点,如下所示:
const ORIGIN = {
x: 0,
y: 0
} as const;
这等同于(并且比以下声明更简洁):
const ORIGIN: {
readonly x: 0;
readonly y: 0;
} = {
x: 0,
y: 0
};