一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情。
本文的翻译于<<Effective TypeScript>>, 特别感谢!! ps: 本文会用简洁, 易懂的语言描述原书的所有要点. 如果能看懂这文章,将节省许多阅读时间. 如果看不懂,务必给我留言, 我回去修改.
技巧23: 一次性新建object
在ts中, 一个变量的值可能会变, 但是类型一般不会变. 所以你应该一次性新建object, 而不是一步一步的建立.
这是js新建一个object的方法:
const pt = {};
pt.x = 3;
pt.y = 4;
在ts中, 会报错:
const pt = {};
pt.x = 3;
// ~ Property 'x' does not exist on type '{}'
pt.y = 4;
// ~ Property 'y' does not exist on type '{}'
这是因为, 在第一行, pt的类型被推断为 {}. 只有已知的属性值能够修改.
如果进行显示类型标注, 会得到相反的报错:
interface Point { x: number; y: number; }
const pt: Point = {};
// ~~ Type '{}' is missing the following properties from type 'Point': x, y
pt.x = 3;
pt.y = 4;
解决办法就是, 一次性定义好object:
const pt = {
x: 3,
y: 4,
}; // OK
如果想一步一步来创建object, 可以断言来解决:
const pt = {} as Point;
pt.x = 3;
pt.y = 4; // OK
更好的方法就是: 显示类型注释同时一次性新建object:
const pt: Point = {
x: 3,
y: 4,
};
如果想用几个小object新建一个大object, 也应该尽量一步建立好, 避免多步建立:
const pt = {x: 3, y: 4};
const id = {name: 'Pythagoras'};
const namedPoint = {};
Object.assign(namedPoint, pt, id);
namedPoint.name;
// ~~~~ Property 'name' does not exist on type '{}'
可以通过object扩展操作符,'...':
const namedPoint = {...pt, ...id};
namedPoint.name; // OK, type is string
也可以使用...一步一步创建object, 关键是在每一步升级的时候, 用新的变量得到新的type:
const pt0 = {};
const pt1 = {...pt0, x: 3};
const pt: Point = {...pt1, y: 4}; // OK
这么迂回的方法新建一个简单的object,显得没有必要. 但是当你需要给object添加一个属性,这又是一个非常有用的技术.
如果想要有条件的添加属性, 可以这样:
declare let hasMiddle: boolean;
const firstLast = {first: 'Harry', last: 'Truman'};
const president = {...firstLast, ...(hasMiddle ? {middle: 'S'} : {})};
将鼠标悬浮到 president 上, 你会看到其类型:
const president: {
middle: string;
first: string;
last: string;
} | {
first: string;
last: string;
}
这里的 middle 不是可选字段:
resident.middle
// ~~~~~~ Property 'middle' does not exist on type
// '{ first: string; last: string; }'
如果想把option变成可选字段:
function addOptional<T extends object, U extends object>(
a: T, b: U | null
): T & Partial<U> {
return {...a, ...b};
}
const president = addOptional(firstLast, hasMiddle ? {middle:
'S'} : null);
president.middle // OK, type is string | undefined