1. 对象字面量的惰性初始化
在 JavaScript 中,像这样用字面量初始化对象的写法十分常见:
let foo = {};
foo.bar = 123;
foo.bas = 'Hello World';
但在 TypeScript 中,同样的写法就会报错:
let foo = {};
foo.bar = 123; // Error: Property 'bar' does not exist on type '{}'
foo.bas = 'Hello World'; // Error: Property 'bas' does not exist on type '{}'
这是因为 TypeScript 在解析 let foo = {}
这段赋值语句时,会进行“类型推断”:它会认为等号左边 foo
的类型即为等号右边 {}
的类型。由于 {}
本没有任何属性,因此,像上面那样给 foo
添加属性时就会报错。
最好的解决方案就是在为变量赋值的同时,添加属性及其对应的值:
let foo = {
bar: 123,
bas: 'Hello World'
};
快速解决方案
let foo = {} as any;
foo.bar = 123;
foo.bas = 'Hello World';
折中的解决方案
当然,总是用 any 肯定是不好的,因为这样做其实是在想办法绕开 TypeScript 的类型检查。那么,折中的方案就是创建 interface,这样的好处在于:
方便撰写类型文档
TypeScript 会参与类型检查,确保类型安全
请看以下的示例:
interface Foo {
bar: number;
bas: string;
}
let foo = {} as Foo;
foo.bar = 123;
foo.bas = 'Hello World';
// 使用 interface 可以确保类型安全,比如我们尝试这样做:
foo.bar = 'Hello Stranger'; // 错误:你可能把 `bas` 写成了 `bar`,不能为数字类型的属性赋值字符串
如果实在不想写interface,为避免object.p
找不到属性,可以尝试使用 object['p']
即对象的数组取值写法,
2. 关于interface
TS中的interface接口和Java,PHP等语言中的接口不太一样,在TS中接口用来描述类型。
interface Person {
name: string;
// 只能在对象刚刚创建的时候修改其值
readonly age: number;
// 可选属性
hobby?: string;
}
let zhangsan = {} as Person;
错: zhangsan.age = 10;
age 是只读属性
对: let zhangsan = {age: 10} as Person;
错: let zhangsan = {nickname: 'xx'} as Person;
nickname不属于Person类型。
readonly vs const
最简单判断该用readonly还是const的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用 const,若做为属性则使用readonly。
有时候我们希望一个接口允许有任意的属性,可以使用如下方式:
interface Person {
name: string;
readonly age: number;
hobby?: string;
[propName: string]: any;
}
使用 [propName: string] 定义了任意属性取 string 类型的值。
需要注意的是,一旦定义了任意属性,那么确定属性和可选属性都必须是它的子属性:
所以 let zhangsan = { name: 'xx', age: 18, nickname: 'xx'} as Person;
不会报错。
也可以这么写 let lisi: Person = { name: 'lisi', age: 20 }
这个功能在有些地方很有用,比如一个组件的config对象类型。可允许传入任意名称的属性。当然属性值得是字符串。
3. 枚举类型
当我们需要定义一组有共同特点的变量,可以使用枚举类型。
比如我们要实现下面的页面,这个页面有两个地方可以切换,一个是包含Ad Creative,Images和Videos的Tab,一个是显示方式Grid还是table。点击不同的按钮,页面切换不同的效果。
image.png
image.png
代码实现
export enum DisplayTab {
Creative,
Image,
Video,
}
export enum DisplayMode {
Table,
Grid,
}
默认下 DisplayTab.Creative 等于 0,即起始从0开始。
也可以改变起始值
export enum DisplayTab {
Creative = 3,
Image, // 4
Video, // 5
}
网友评论