2024/10/20: TypeScript 学习笔记三:TypeScript 类型系统

一、TypeScript 提供的对应类型:

  • boolean
  • string
  • number
  • bigint
  • undefined
  • null
  • symbol

 

二、object 类型仅能够赋值给以下三种类型:

  • 顶端类型 any 和 unknown
  • Object 类型
  • 空对象类型字面量“{}”

注:所有类型都是顶端类型的子类型,所以object 能够赋值给顶端类型 any 和 unknown

const nonPrimitive:object = {}

const a:any = nonPrimitive
const b: unknown = nonPrimitive

 

Object 类型描述了所有对象都共享的属性和方法,所以很自然地表示对象类型的 object 类型能够赋值给 Object 类型。示例如下:

const nonPrimitive: object = {}

const obj: Object = nonPrimitive

 

object 类型也能够赋值给空对象类型字面量 “{}”。示例如下:

const nonPrimitive:object = {}

const obj:{} = nonPrimitive

 

三、定义一个常用的 object 类型的数据

let point:{

readonly x: number;   // 只读属性
// 只读属性的值在初始化后不允许再被修改。

y:number;

z?:  number; // typescript  会自动 定义成 z?: number | undefined   
// 在严格模式下, null 和 undefined 是区别对待的。不能将 null 赋值给 z
// 在 非严格模式下,null  与 undefined  均可以赋值给 可选属性 z 。

}


// 正确
point = {x: 0, y: 0}

point.x = 1 //编译错误,不允许给 x 赋值,因为它是只读属性

 

 

四、空对象类型字面量

空对象字面量表示不带任何属性的对象类型,因此不允许在 “{}” 类型上访问任何自定义属性。示例如下:

const  point: {} = {x: 0, y: 0}

point.x  // 编译错误,属性x 不存在于 类型 {}

在 空对象类型字面量 “{}” 上,允许访问对象公共的属性和方法,也就是 Object 类型上定义的方法和属性。示例如下:

const  point: {}  = {x: 0, y:0}

point.valueOf();

现在可以发现 空对象类型字面量 “{}” 与 Object 类型十分相似。事实上也是如此。单从行为上来看两者是可以互换使用的。例如,除了 undefined 和 null 值外,其他任何值都可以赋值给 空对象类型字面量 “{}” 和 Object 类型。同时,空对象类型字面量 “{}” 和 Object 类型之间也允许互相赋值。示例如下:

let a: Object = 'hi'
let b: {} = ‘hi’

a = b;
b = a

两者的区别在于语义上。全局的 Object 类型用于描述对象公共的属性和方法,它相当于一种专用类型,因此程序中不应该将自定义变量、参数 等类型直接声明为 Object 类型。空对象类型字面量 “{}” 强调的是不包含属性的对象类型,同时也可以作为 Object 类型的代理来使用。最后也要注意下:在某些场景中新的 object 类型可能是更加合适的选择。

 

五、弱类型

弱类型指的是同时满足以下条件的对象类型:

  • 对象类型中至少包含一个属性。
  • 对象类型中所有属性都是可选属性
  • 对象类型中不包含字符串索引签名、数值索引签名、调用签名和构造签名

例如,下例中 config 变量的类型是一个弱类型

let config: {
  url?: string;
  async?: boolean;
   timeout?: number  
}

 

六、多余属性

const point: {x: number} = {x: 0, y: 0}  //  y 是多余属性

多余属性会影响类型间的子类型兼容性以及赋值兼容性,也就是说编译器不允许在一些操作中存在多余属性。

 

多余属性检查在绝大多数场景中都是合理的。如果确定不想让编译器对代码进行多余属性检查,有多种方法能够实现这个效果。如下

  • 使用类型断言,这是推荐方法

  类型断言能够对类型进行强制转换。例如,我们可以将对象字面量{x:0,y:0}的类型强制转换为 {x: 0} 类型。

  类型断言能够绕过多余属性检查的真正原因是:处于类型断言表达式中的对象字面量将不再是“全新的对象字面量类型”,因此编译器也就不会对其进行多余属性检查。

  例如:

// 无编译错误
const p0: {x:number} = {x: 0, y: 0} as {x:number}

// 无编译错误
const p1: {x: number} = {x: 0, y: 0} as {a:  0, y: 0}

 

  • 启用 “--suppressExcessPropertyErrors” 编译选项

  启用该编译选项能够完全禁用整个 TypeScript 工程的多余属性检查,但同时也将完全失去多余属性检查带来的帮助。

  我们可以在 tsconfig.json 配置文件中或命令行上启动该编译选项。例如:

{
    “compilerOptions”: {
        "suppressExcessPropertyErrors": true
    }
}

 

  • 使用 “// @ts-ignore” 注释指令

  该注释指令能够禁用针对某一行代码的类型检查

// @ts-ignore
const point: {x: number} = {x: 0, y: 0}

 

  • 为目标对象类型添加索引签名

  若目标对象类型上存在索引签名,那么目标对象可以接受任何属性,因此也就谈不上多余属性。例如:

const point: {
    x: number;
    [prop: string]: number; // 索引签名  
} = {x: 0, y: 0}

 

  • 最后一种方法也许不是很好理解。如果我们先将对象字面量赋值给某个变量,然后再将该变量赋值给目标对象类型,那么也就不会执行多余属性检查。

  这种方法能够生效的原理与类型断言类似,那就是令源对象类型不为“全新的对象字面量类型”,于是编译器将不执行多余属性检查。例如:

const temp = {x: 0, y:0}

//无编译错误
const point : {x: number} = temp

 

posted on 2024-10-20 22:34  bala001  阅读(17)  评论(0编辑  收藏  举报

导航