外观
外观
怡然
1901字约6分钟
2024-10-31
const obj: {
x: number;
y: number;
} = { x: 1, y: 1 };
const obj: {
x: number;
y: number;
add(x: number, y: number): number;
// 或者写成
// add: (x:number, y:number) => number;
} = {
x: 1,
y: 1,
add(x, y) {
return x + y;
},
};
type User = {
name: string;
age: number;
};
type Name = User["name"]; // string
interface
命令,可以把对象类型提炼为一个接口。// 写法一
type MyObj = {
x: number;
y: number;
};
const obj: MyObj = { x: 1, y: 1 };
// 写法二
interface MyObj {
x: number;
y: number;
}
const obj: MyObj = { x: 1, y: 1 };
TypeScript
不区分对象自身的属性和继承的属性,一律视为对象的属性。interface MyInterface {
toString(): string; // 继承的属性
prop: number; // 自身的属性
}
const obj: MyInterface = {
// 正确
prop: 123,
};
const obj: {
x: number;
y?: number;
} = { x: 1 };
undefined
,下面两种写法是等效的。type User = {
firstName: string;
lastName?: string;
};
// 等同于
type User = {
firstName: string;
lastName: string | undefined;
};
undefined
。const user: {
firstName: string;
lastName?: string;
} = { firstName: "Foo" };
// 写法一
let firstName = user.firstName === undefined ? "Foo" : user.firstName;
let lastName = user.lastName === undefined ? "Bar" : user.lastName;
// 写法二
let firstName = user.firstName ?? "Foo";
let lastName = user.lastName ?? "Bar";
readonly
关键字,表示这个属性是只读属性,不能修改。const person: {
readonly age: number;
} = { age: 20 };
person.age = 21; // 报错
readonly
修饰符并不禁止修改该对象的属性,只是禁止完全替换掉该对象。interface Home {
readonly resident: {
name: string;
age: number;
};
}
const h: Home = {
resident: {
name: "Vicky",
age: 42,
},
};
h.resident.age = 32; // 正确
h.resident = {
name: "Kate",
age: 23,
}; // 报错
interface Person {
name: string;
age: number;
}
interface ReadonlyPerson {
readonly name: string;
readonly age: number;
}
let w: Person = {
name: "Vicky",
age: 42,
};
let r: ReadonlyPerson = w;
w.age += 1;
r.age; // 43
readonly
关键字,还有一种方法,就是在赋值时,在对象后面加上只读断言as const
。const myUser = {
name: "Sabrina",
} as const;
myUser.name = "Cynthia"; // 报错
TypeScript
会以声明的类型为准。const myUser: { name: string } = {
name: "Sabrina",
} as const;
myUser.name = "Cynthia"; // 正确
TypeScript
允许采用属性名表达式的写法来描述类型,称为“属性名的索引类型”。type MyObj = {
[property: string]: string;
};
const obj: MyObj = {
foo: "a",
bar: "b",
baz: "c",
};
上面示例中,类型
MyObj
的属性名类型就采用了表达式形式,写在方括号里面。[property: string]
的property
表示属性名,这个是可以随便起的,它的类型是string
,即属性名类型为string
。也就是说,不管这个对象有多少属性,只要属性名为字符串,且属性值也是字符串,就符合这个类型声明。
JavaScript
对象的属性名(即上例的property
)的类型有三种可能,除了上例的string
,还有number
和symbol
。type T1 = {
[property: number]: string;
};
type T2 = {
[property: symbol]: string;
};
JavaScript
语言内部,所有的数值属性名都会自动转为字符串属性名。type MyType = {
[x: number]: boolean; // 报错
[x: string]: string;
};
type MyType = {
foo: boolean; // 报错
[x: string]: string;
};
const {
id,
name,
price,
}: {
id: string;
name: string;
price: number;
} = product;
B
满足 对象 A
的结构特征,TypeScript
就认为对象 B
兼容对象 A
的类型,这称为“结构类型”原则(structual typing)。const A = {
x: number;
};
const B = {
x: number;
y: number;
};
// B兼容A,可以使用A的地方,就可以使用B
type myObj = {
x: number;
y: number;
};
function getSum(obj: myObj) {
let sum = 0;
for (const n of Object.keys(obj)) {
const v = obj[n]; // 报错
sum += Math.abs(v);
}
return sum;
}
函数
getSum()
要求传入参数的类型是myObj
,但是实际上所有与myObj
兼容的对象都可以传入。这会导致const v = obj[n]
这一行报错,原因是obj[n]
取出的属性值不一定是数值(number
),使得变量v的类型被推断为any
。如果项目设置为不允许变量类型推断为any
,代码就会报错。
TypeScript
的严格字面量检查(strict object literal checking)。如果字面量的结构跟类型定义的不一样(比如多出了未定义的属性),就会报错。const myPoint = {
x: 1,
y: 1,
z: 1,
};
const point: {
x: number;
y: number;
} = myPoint; // 正确
let myOptions = {
title: "我的网页",
darkmode: true,
};
const Obj: Options = myOptions;
let x: {
foo: number;
[x: string]: any;
};
x = { foo: 1, baz: 2 }; // Ok
suppressExcessPropertyErrors
,可以关闭多余属性检查。{
"compilerOptions": {
"suppressExcessPropertyErrors": true
}
}
TypeScript
的一种特殊值,也是一种特殊类型。Object.prototype
的属性。TypeScript
不允许动态添加属性,所以对象不能分步生成,必须生成时一次性声明所有属性。...
)合成一个新对象。const pt0 = {};
const pt1 = { x: 3 };
const pt2 = { y: 4 };
const pt = {
...pt0,
...pt1,
...pt2,
};
let d: {};
// 等同于
// let d:Object;
d = {};
d = { x: 1 };
d = "hello";
d = 2;