typescript中对象属性可选属性与只读属性与索引签名
可选属性
type类型别名
type 会给一个类型起个新名字。 type 有时和 interface 很像,但是可以作用于原始值(基本类型),联合类型,元组以及其它任何你需要手写的类型。
interface
TypeScript 的核心原则之一是对值所具有的结构进行类型检查。 而接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
这段代码给Pearent 定义了三个属性---Shape,xPop,yPop
后面跟的 ? 代表的是可选也就是可传入可不传入。
再函数形参中我们进行xPop = 0设置的意义是如果不传入xPop,则默认值设为 0
interface Pearent {
Shape:Shape,
xPop?:number,
yPop?:number
}
###
![](https://img2022.cnblogs.com/blog/2752939/202202/2752939-20220223111442584-1618479204.png)
function Pearent({Shape,xPop = 0,yPop = 0}:Pearent){
let xpop = xPop
console.log("🚀 ~ file: 02-可选属性.ts ~ line 10 ~ Pearent ~ xPop", xpop)
}
Pearent({Shape:`小红`})
Pearent({Shape:1,xPop:1})
只读属性
在属性前面加上readonly 关键字,变成只读属性
interface Home {
readonly resident :{
age:number,
name:string
}
}
function visit(home:Home){
console.log(home.resident.age);
// 但是可以修改只读属性内部属性
home.resident.age ++
}
function evict (home:Home){
// 修改只读属性就会报错
// home.resident= {
// name:`小红`
// age:18
// }
}
可以将可写的属性赋值给不可写的属性,实现属性修改
// 可读属性
interface person{
name:string,
age:number
}
//不可读写属性
interface readonlyPerson{
readonly name:string,
readonly age:number
}
//可读写数据
let newPerson:person = {
name:`小红`,
age:18
}
//将可读写数据赋给不可读写数据
let newPersons:readonlyPerson = newPerson
console.log(newPersons.age);//18
newPerson.age ++
console.log(newPersons.age);//19
索引签名
索引签名在实际开发中经常用到,例如服务端接口返回了很多数据但是存在我们不需要用的,如果定义接口的时候不定义它们会报错,这时我们使用索引签名,就可以避免这个问题
注意:TypeScript 的索引签名必须是 string 或者 number。索引签名的名称(如:{ [index: string]: { message: string } } 里的 index )除了可读性外,并没有任何意义。例如:如果有一个用户名,你可以使用 { username: string}: { message: string },这有利于下一个开发者理解你的代码。当你声明一个索引签名时,所有明确的成员都必须符合索引签名:
interface qingTian {
[props:string]:number
}
let Top = {
x:1,
b:2
}
interface Animal {
name:string
}
interface Dog extends Animal{
befff : string
}
interface Monky {
[index:string]:number|string
name:string
length:number
}
let momky:Monky ={
name:`小花`,
length:2
}
interface readOnly {
readonly [index:number]:string
}
let myarr:readOnly = [`a`,`b`,`c`]
// myarr[0]= b
扩展类型
通过interface定义多个接口类型,用extends继承属性,如果多类型,可以在extend后面的类型中继续加,用‘ ,’逗号链接
interface Zoom {
name:string,
age:number,
color?:string
}
interface Top extends Zoom{
unit:string
}
let address:Top = {
name:`小红`,
unit:`小蓝`,
age:18
}
interface circular {
radius:number
}
interface length{
length:number
}
interface less extends circular,length{
ref:boolean
}
交叉类型
交叉类型其实和扩展类型差不多,都是让两个类型为一个类型或变量服务。
interface RNG {
Ming:string
}
interface OMG{
Fafer:string
}
// type LPL = OMG & RNG
// let LPL:LPL ={
// Fafer:`小红`,
// Ming:`小明`
// }
function LPL(LPL:RNG&OMG){
console.log(LPL.Fafer);
console.log(LPL.Ming);
}
LPL({
Ming:`小明`,
Fafer:`小李`
})
看上去交叉类型和扩展类型是相似的,但是他们也有一丝的差别,就是在处理冲突的时候。
interface 允许变量名相同,并且会把相同变量名的属性整合在一起。
type 不允许创建相同变量名
// interface Sister {
// name:string
// }
// interface Sister{
// age:number
// }
// let person:Sister ={
// name:`小红`,
// age:12
// }
type Sister ={
name:string
}
type Sister
泛型类型对象
//这样判断为any失去了定义类型的意义
interface x {
contens:any
}
let box:x ={
contens:`什么类型都可以`
}
//使用unkown
interface y{
contens:unknown
}
let y:y = {
contens:`Hello , word`
}
// 使用类型缩小
if(typeof y.contens===`string`){
console.log(y.contens.toLocaleLowerCase());
}
// 使用类型断言
console.log((y.contens as string).toLocaleLowerCase());
// 使用函数重载定义
interface numberBOX {
contents:number
}
interface stringBox{
contents:string
}
interface booleanBox{
contents:boolean
}
function setContents (box:numberBOX,newBox:number):void
function setContents (box:stringBox,newBox:string):void
function setContents (box:booleanBox,newBox:boolean):void
function setContents(box:{contents:any},newBox:any){
box.contents = newBox
}
// 使用泛型对象定义
interface Box<type> {
contents:type
}
interface Apple{
// ...
}
let a:Apple = {}
type AppleBox = Box<Apple>
let ab:AppleBox = {
contents:a
}
type Box1<type> = {
contents:type
}
type Oneornull<type> = type|null
type OneorMany<type> = type | type[]