TypeScript学习(四):Handbook -> Object Types

294 阅读2分钟

strictNullChecks

xPos是可选属性,可能是 opts.xPos 可能是undefined。TS 设置中开启 strictNullChecks 后,TS 会有提示:(property) PaintOptions.xPos?: number | undefined。

interface PaintOptions{
    xPos?: number
}

function paintShpae(opts: PaintOptions)
    let xPos = opts.xPos;
}

可以给个默认值 ---> xPos: number

function paintShpae({ xPos = 0 }: PaintOptions)
    let xPos = opts.xPos;
}

只读属性

readonly 只对 object 的浅层属性有效。

interface Home {  
  readonly resident: { 
    name: string; age: number 
  };
}

function visitForBirthday(home: Home) {  
  home.resident.age++;
}

只读属性类型的变量一定不能写入吗?

TS 在对比两个类型的是,并不关心属性是否为只读。只要两个类型的属性一样,那么就认为是相同的类型,因此,只读属性也是可以写入的

// 普通属性
interface Person {  name: string;  age: number;}

//只读属性
interface ReadonlyPerson { 
  readonly name: string;  
  readonly age: number;
}

let writablePerson: Person = {  
  name: "Person McPersonface",  
  age: 42,
 };

// works
let readonlyPerson: ReadonlyPerson = writablePerson;
console.log(readonlyPerson.age); // prints '42'
writablePerson.age++;
console.log(readonlyPerson.age); // prints '43'

索引签名 Index Signatures

使用场景:不知道对象的素有属性名称,但是知道属性对应的值的类型。因此可以使用索引签名去描述对象的值。

下方 index 的属性只能是 string 或者 number。

interface StringArray{
    [index:number]:string | number
}

继承类型 Extending Types

interface 可以继承多个interface,但是被继承的这几个 interface 如有有相同的属性,那么属性的类型必须相同。

交叉类型 intersection Types

使用 & 符号,与类型别名一起使用。

交叉类型与继承类型功能相似,但是本质上是不同的。

interface test {
    foo: (value:string) => number
}

interface test1 {
    foo: (value:string) => string
}

interface a extends test, test1 {}  // 报错
type a = test & test1 // 不报错

通用的对象类型

对象的值可以是任意类型时,最好使用 unknown 代替 any。在编码中,可以使用类型检查或者断言来实现。

也可以结合泛型

interface Box<T>{
    contents: T
}

function setCntents<T>(box: Box<T>, newContents:T){
    box.contents = newContents
}

数组

数组类型的对象也可以给定类型

interface Array<T>{
    length: number;
    pop():T | undefined;
    push(...items: T[]):number
}

ReadonlyArray

TS 类型中 ReadonlyArray 是一个只读的数组,在 JS 中不能 new ReadonlyArray。

也可以使用 readonly 关键字

readonly string[]
ReadonlyArray<T>

此外,只读数组不可以赋值给普通数组

// does not work
let x: readonly string[] = []
let y: string[] = []
x = y
// The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
y = x

?可选属性也会影响数组的长度

type Either2dOr3d = [number, number, number?]
function setCoordinate(coord: Either2dOr3d){
    const [x, y, z] = coord
    // coord.lenght --> 2 | 3
}

元组

type StringNumberBooleans = [string, number, ...boolean[]]
type StringBooleansNumber = [string, ...boolean[], number]
type BooleansStringNumber = [...boolean[], string, number]

只读元组

大多情况下,元组被创建后一般是不会更改的,因此使用 readonly 是一种好的习惯。

TS会把 字面量数组 推断成 const之后,TS 会把数组推导成 --> 只读元组。

let point = [3, 4] as const 
function distanceFormOrigin([x, y]: [number, number]){
    return Math.sqrt(x ** 2 + y ** 2)
}

//  The type 'readonly [3, 4]' is 'readonly' 
//  and cannot be assigned to the mutable type '[number, number]
distanceFormOrigin(point)