初识类型

本贴最后更新于 1302 天前,其中的信息可能已经东海扬尘

图标

✅ 推荐使用
🐱‍🐉

类型

类型是一系列及可以对其执行的操作

如:String 类型包含所有字符串,以及可以对字符串执行的操作(+、||、&& 等),以及可以在该类型上调用的方法 (.fixed()、.toString() 等)

类型注解

function squareOf(n: number){
	return n * n
}

squareOf(2) // 4
squareOf('z') // 类型“string”的参数不能赋给类型“number”的参数

// n: number 中的 : number 就是 n 参数的 类型注解,限定该参数的类型为 number 类型

any

## any
let a: any = 666
let b: any = ['danger']
let c = a + b
// 正常情况 c 将报错

unknown

如果你确实无法预知一个值的类型,不要使用 any , 应该使用 unknown,

与 any 类似,但有区别, (TS 会要求你检查,细化类型

 // unknown
  let a: unknown = 30
  let b = a === 123
  let c = a + 10
  if(typeof a === 'number'){
    let d = a + 10
    console.log(d)
  }
  1. ts 不会把任何值推导为 unknown 类型,必须显示注解。(a)
  2. unknown 类型的值可以比较。 (b)
  3. 但是直线操作时不能假定 unknown 类型的值为某种特定类型 (c), 必须向 TS 证明一个值确实时某个类型。

boolean

  // boolean
let a = true
var b =false
const c =true
let d: boolean = true
let e: true = true
let f: true = false

为什么 c 的类型是 true?
1. 使用 const 声明的值,赋值之后便无法修改。因此TS 推导出来的是范围最窄的类型。
把类型设为某个值,就限制了 c 在所有布尔值中只能取指定的那个值。这个特性称为 类型字面量(type literal)

  1. 可以让 TS 推导出值得类型为 boolean(a 和 b) ✅
  2. 可以让 TS 推导出值为某个具体得布尔值(c) ✅
  3. 可以明确告诉 TS ,值得类型为 boolean (d)
  4. 可以明确告诉 TS,值为某个具体得布尔值(e 和 f)

number

number 包括所有的数字: 整数、浮点数、正数、负数、Infinity、NaN 等。

  let a = 1234
  var b = Infinity * 0.10
  const c = 5678
  let d =  a < b
  let e: number = 100 
  let f: 26.218 = 26.218
  let g: 26.218 = 10

  1. 可以让 TS 推导出值得类型为 number(a 和 b) ✅
  2. 可以使用 const, 让 TS 推导出值为某个具体得数字 (c)
  3. 可以明确告诉 TS ,值得类型为 boolean (e)
  4. 可以明确告诉 TS,值为某个具体的数字(f 和 g)

🐱‍🐉 在处理较长的数字时,为了便于辨识数字,建议使用数字分隔符 。在类型和值所在的位置上都可以使用数字分隔符。

let  一百万 = 1_000_000 
let 两百万: 2_000_000 = 2_000_000

bigint

bigint 时 JS 和 TS 新引入的类型, 处理较大整数时,不用再担心舍入误差。

  // bigint
  let a = 1234n
  const b = 5678n
  var c = a + b
  let d = a + b
  let e = 88.5n
  let f: bigint = 100n
  let g: 100n = 100n
  let h: bigint = 100

与 Boolean 和 number 一样,声明 bigint 类型也有四种方式,尽量使用自动推导。

string

  let a = 'hello'
  var b = 'billy'
  const c = '!'
  let d = a + '' + b + c
  let e: string = 'zoom'
  let f: 'john' = 'john'
  let g: 'john' = 'zoe'

同上

symbol

经常用于代替对象和映射的字符串建,确保使用正确的已知建

  let a = Symbol('a')
  let b:  Symbol = Symbol('b')
  var c__ = a === b
  let d = a + 'x'
  const e = Symbol('e')
  const f: unique Symbol = Symbol('f')
  let g: unique Symbol = Symbol('f')

  let h = e === e
  let i = e === f
  1. 使用 const 声明的符号,TS 推导为 unique symbol 类型。 在代码编辑器中显示为 typeof yourVariableName, 而不是 unique symbol.
  2. 可以显示注解 const 变量类型为 unique symbol.
  3. unique symbol 类型的值始终与自身相等。
  4. TS 在编译时知道一个 unique symbol 类型的值绝不会与另一个 unique symbol 类型的值相等。

object

  let a: {
    b: number //1
    c?: string // 2
    [key: number]: boolean // 3  索引标签 
  }
  // 1. a 有个类型为 number 的 属性 b.
  // 2. a 可能有个类型为string 的属性 c. 如果有属性c, 其值可以为 undefined.
  // 3. a 可能有任意多个数字属性,其值为布尔值。

  let apsa : {
    [key: string]: string
  } = {
    'a' : 'aaa',
    'b' : 'bbb'
  }

  let apsb: {
    str: string
  } = {
    str: 'aaa',
    stc: 'bbb'
  }

  let user: {
    readonly firstName: string // 只读
  } = {
    firstName: 'cc'
  }

索引标签 (翻译的怪怪的)
[key: T]: U
记住: 键的类型(T) 必须可赋值给 number 或 string. ( JS 对象的键为字符串; 数组时特殊的对象,键为数字)

对象字面量表示法有一个特例: 空对象类型 ({}). 除 null 和 undefined 之外的任何类型都可以赋值给空对象类型。(尽量避免使用)

 let danger: {}
 danger = {} 
 danger = {x : 1}
 danger = []
 danger = 2
  1. 对象字面量表示法( {a: string} ), 也称对象的结构。 如果知道对象有那些字段,或者对象的值都为相同的类型,使用这种方式。
  2. 空对象字面量表示法({}). 尽量避免使用。
  3. object 类型。 如果需要一个对象,但对对象的字段没有要求,可以使用。
  4. Object 类型。 尽量避免使用。

类型别名

// 给类型声明别名
// 干脆把他当作 声明 变量 的方式就完事了
  type Age = number
  type Preson = {
    name: string
    age: Age
  }
  
  type Age = string // 同一类型不能声明两次

同一类型不能声明两次
块级作用域

并集类型和交集类型

// 就是数学书里的并集和交集

| 并集
& 交集

  type Cat = { name: string, purrs?: boolean }
  type Dog = { name: string, barks?: boolean, wags?: boolean}
  type CatOrDogOrBoth = Cat | Dog
  type CatAndDog = Cat & Dog

  let a: CatOrDogOrBoth = {
    name: '123',
    wags: true
  }

  let b: CatAndDog = {
    name: 'sss'
  }


  function trueOrNull(isTrue: boolean) {
    if(isTrue){
      return 'true'
    }
    return null
  }

  trueOrNull(true)

数组

  let a = [1,2,3]
  var b____ = ['a', 'b']
  let c: string[] = ['a']
  let d= [1, 'a']
  const e = [2, 'b']

  let f = ['red']
  f.push('bule')
  f.push(true)

  let g = []
  g.push(1)
  g.push('red')
  
  let h: number[] = []
  h.push(1)
  h.push('red')

🐱‍🐉 TS 支持两种注解数组类型的语法: T[] 和 Array。 二者作用和性能无异。
数组应该保持同质 , 即保证数组中的元素都具有相同的类型。 ( why? ) (f)

与对象一样, 使用 const 声明数组不会导致 TS 推导出范围类型更窄的类型

数组离开定义时所在的作用域后,TS 将最周确定一个类型,不在扩张

function buildArray () {
    let a = []
    a.push(1)
    a.push('x')
    return a 
}
let myArray = buildArray()
myArray.push(true)

元组

元组时 array 的子类型, 是定义数组的一种特殊方式,长度固定,各索引位上的值具有固定的已知类型。
声明元组时必须显示注解类型。( 因为它和数组都是使用 方括号 )

  let a: [number] = [1]
  // [ 名,姓,出生年份 ] 形式的元组
  let b: [string, string, number] = ['陈', '贝', 1999]
  b = ['陈', '贝', '贝', 1998]
  // 剩余元素
  // 字符串列表,至少有一个元素
  let friends: [string, ...string[]]= ['Sara', 'Tali', 'Chloe']

  // 元素类型不同的列表
  let list: [number, boolean, ...string[]] = [1, false, 'a', 'b', 'c'] 

  // 只读数组和元组
  let as: readonly number[] = [1,2,3]
  let bs: readonly number[] = as.concat(4)
  let three = bs[2]

  as[4] = 5
  as.push(6)

元组类型能正确定义元素类型不同的列表,还能知晓该种列表的长度。这些特性使得元组比数组安全的多,应该经常使用。

null、undefined、void 和 never

类型 含义
null 缺少值
undefined 尚未赋值的变量
void 没有返回值的函数
never 永不返回的函数
 // (a) 一个返回数字或 null 的函数
  function a(x: number) {
    if(x < 10) {
      return x
    }
    return null
  }

  // (b) 一个返回undefined 的函数
  function b() {
    return undefined
  }

  // (c) 一个返回 void 的函数
  function c() {
    let a = 2 + 2
    let b = a * a
  }

  // (d) 一个返回 never 的函数
  function d() {
    throw TypeError ('I always error')
  }

  // (e)
  function e() {
    while (true){
      doSomething()
    }
  }

如果说 unknown 时其他每个类型的父类型, 那么 never 就是其他每个类型的子类型。
理论上: never 类型可以赋值给其他任何类型,在任何地方都能放心使用 never 类型的值。

枚举

枚举的作用时列举类型种包含的各个值。这是一种无序数据结构,把键映射到值上。可以理解为 编译时 键固定的对象,访问键时,TS 将检查指定的键是否存在。

用的少,以后用到再补充把( 作者大大说: 由于使用枚举极易导致安全问题,因此作者建议远离枚举。 )
偷懒,嘿嘿 😎


补充

  1. 索引签名

  2. 明确赋值
    let i: number

    let j = i * 3 // 在赋值前使用了变量“i”

  3. 使用 const 声明对像时的类型推导
    使用 const 声明对象不会导致 TS 把推导的类型缩窄,这是因为 JS 对象时 可变的(属性)

  4. 结构化类型
    🐱‍🐉 一种编程设计风格,只关心对象有那些属性,而不管属性使用什么名称(名义化类型)。在某些语言中也叫鸭子类型

  5. 类型字面量
    仅表示一个值的类型

  6. public firstName: string

    public 是 this.firstName = firstName 的简写

1 操作
duobancc 在 2021-04-29 20:45:22 更新了该帖

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...