假设我们有一个接口结构,描述了响应的消息结构
tsinterface Res {
code: number;
status: string;
data: any;
}
大多数情况下code 与 status 实际值会来自于一组确定值的集合
比如:
0
/ 200
/ 10000
等‘success’
/ "failure"
等但是上面的类型标注太宽泛了,我们既不能在访问 code 时获得精确的提示,也失去了 TypeScript 类型即文档的功能。
这时就需要更精确的字面量类型、联合类型、枚举类型,提供精确地取值标注
例如,我们可以使用字面量类型、联合类型将上面的例子标注的更清楚
tsinterface Res {
code: 10000 | 10001 | 50000;
status: "success" | "failure";
data: any;
}
直接使用值作为类型,即字面量类型(Literal Types),代表着比原始类型更精确的类型,同时也是原始类型的子类型
字面量类型主要包括字符串字面量类型
、数字字面量类型
、布尔字面量类型
和对象字面量类型
,它们可以直接作为类型标注
相关信息
无论是原始类型还是对象类型的字面量类型,它们的本质都是类型而不是值。
它们在编译时同样会被擦除,同时也是被存储在内存中的类型空间而非值空间。
tsconst str: "silon" = "silon";
const num: 599 = 599;
const bool: true = true;
字面量类型比原始类型更精确:
ts// 报错!不能将类型“"silon123"”分配给类型“"silon"”。
const str1: "silon" = "silon123";
const str2: string = "linbudu";
const str3: string = "silon123";
对象字面量类型就是一个对象类型的值,即对象的所有属性都使用字面量进行了定义
tsinterface Tmp {
obj: {
name: "linbudu",
age: 18
}
}
const tmp: Tmp = {
obj: {
name: "linbudu",
age: 18
}
}
联合类型代表了一组类型的可用集合
tsinterface Tmp {
mixed: true | string | 599 | {} | (() => {}) | (1 | 2)
}
相关信息
()
包裹起来(() => {})
就是一个合法的函数类型tsinterface Tmp {
user:
| {
vip: true;
expires: string;
}
| {
vip: false;
promotion: string;
};
}
declare var tmp: Tmp;
if (tmp.user.vip) {
console.log(tmp.user.expires);
}
在这里 user 有两种数据结构,expires 属性只会在一种情况下出现。 一般业务中,通过判断 vip 是否为 true,来收窄后面的类型判断
tstype Code = 10000 | 10001 | 50000;
type Status = "success" | "failure";
枚举并不是 JavaScript 中原生的概念,目前已经加入 Es 提案,但仍处于 stage0 阶段
我们会在业务场景中,列举一系列的值
jsexport const PageUrl = {
Home_Page_Url: "url1",
Setting_Page_Url: "url2",
Share_Page_Url: "url3",
}
使用枚举形式如下
tsenum PageUrl {
Home_Page_Url = "url1",
Setting_Page_Url = "url2",
Share_Page_Url = "url3",
}
const home = PageUrl.Home_Page_Url;
这么做的好处非常明显。
TypeScript 中也可以同时使用字符串枚举值和数字枚举值
enum Mixed { Num = 599, Str = "linbudu" }
ts// Items.Foo , Items.Bar , Items.Baz的值依次是 0,1,2 。
enum Items {
Foo,
Bar,
Baz
}
tsenum Items {
// 0
Foo,
Bar = 599,
// 600
Baz
}
tsconst returnNum = () => 100 + 499;
//
enum Items {
Foo = returnNum(),
Bar = 599,
Baz
}
//
enum Items {
Baz,
Foo = returnNum(),
Bar = 599,
}
枚举和对象的重要差异在于:
tsenum Items {
Foo,
Bar,
Baz
}
const fooValue = Items.Foo; // 0
const fooKey = Items[0]; // "Foo"
相关信息
值为数字
的枚举成员才能够进行这样的双向枚举
字符串
枚举成员仍然只会进行单次映射
tsenum Items {
Foo,
Bar = "BarValue",
Baz = "BazValue"
}
// 编译结果,只会进行 键-值 的单向映射
"use strict";
var Items;
(function (Items) {
// 数值类型
// 这里的 obj[obj[k] = v] = k 本质上就是进行了 obj[k] = v 与 obj[v] = k 这样两次赋值
Items[Items["Foo"] = 0] = "Foo";
// 非数字类型只有一次赋值
Items["Bar"] = "BarValue";
Items["Baz"] = "BazValue";
})(Items || (Items = {}));
常量枚举和枚举相似,只是其声明多了一个 const:
tsconst enum Items {
Foo,
Bar,
Baz
}
const fooValue = Items.Foo; // 0
他与普通枚举的区别在于访问性与编译产物
以上的代码会被编译为如下形式:
const fooValue = 0 /* Foo */; // 0
本文作者:Silon汐冷
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!