TypeScript全解:类型(上)

JS/TS 中有哪些数据(data)类型(type)

  • JS
    • null, undefined, string, number, boolean, bigint, symbol, obejct(含 Array、Function、Date...)
  • TS
    • 以上所有,加上 void, never, enum, unknown, any,再加上自定义类型 type, interface

如何理解 TS 的数据类型

和 JS 的区别在于,JS 说到数据类型的时候,是说这个值是字符串,这个值就是数字,

那么 TS 呢,指的是一类数据的类型,而不是一个,所以说得从集合的角度来理解
例如:

  • number 是指 1 | 1.1 | 1.2 | .... | 2 | ...
  • string 是指 a | b | ... | z | ...
  • boolean 是指 true | false
  • Object 是指 {...} | Array | Function | String | Number | ... | RegExp | ...

注意:Object 这里 为什么还会有 String,Number?
这里涉及到 JS 的历史遗留知识,42 VS new Number(42)
基本没有人会用 new Number(42) 来表示“42”
42 就是一个普通的值
而 new Number(42),则表示这是一个对象:

{
  constructor: ....,
  toFixed: ...,
  toString: ...,
  valueOf: function() {
    return 42 
  }
}

但是 (42).toFixed(),为什么可以正常运行,明显不合逻辑
当然是因为 JS 的包装对象,在你写上述代码的时候,JS 帮你做了这四步:

  1. let temp = new Number(42); 2. value = temp.toFixed(2); 3. 删除 temp; 4. 返回 value;

所以 JS 中的 Number, String, Boolean 只用于包装对象,正常来说不会用到他们,当然在 TS 里也不用

那么问题又来了,var n = 42; n.xxx = 2; console.log(n.xxx),会打印出什么呢?

用类型签名和Rercord描述对象

type A = Object

const a:A = 1
const a1:A = () => {}
const a2:A = {}
const a3:A = /a+b/

这和 any 有什么区别嘛,所以我们一般在 TS 里不用 Object

那么用什么呢?

  • 用 class / constructor 描述,例如:const a: Function = () => {}
  • 用 type 或 interface 描述,例如:type Person = { name: string; age: number; },我们比较常用的是索引签名 type A = { [k: string]: number }(这个语法特别丑),所以我们一般用 Record<string, number>

思考:key 的类型可以不是 string/symbol 吗?

试一下就知道了

type A = Record<number, number>

const a: A = {
  name: 1,
  123: 6,
}

当 key 的类型是 number 的时候,虽然 js 不支持,但 ts 只会做字面量上的检查

用[]和Array泛型来描述数组对象

type A = string[]
const a: A = ['h', 'i']
// 等价于
type A = Array<string>
const a: A = ['h', 'i']

type D = [string, 'string'] // 二元组
const d: D = ['h', 'i']

type D = [string, 'string', 'string'] // 三元组
const d: D = ['h', 'i', 'n']

type E = [number[], string]
const e: E = [[1,2,3,4], 'abc']

思考

type A = [1,2,3]
const a: A = ???

只能为 [1,2,3],注意这里的 type A 不是值,1 也是类型,是 number 的子集

描述函数对象

type FnA = (a, number, b: number) => number
const fnA: FnA = () => 1 // 这里即使不写参数也可以,ts 在这里的检查是松散的,后面会在类型兼容中细讲

返回值为 void 和 undefined 的时候

type FnA = () => void
const fnA: FnA = () => {}

type FnB = () => undefined
const fnB: FnB = () => {} // 这里报错,似乎与 js 的表现不太一样,按理来说 js 的函数不写返回值,那么默认就是返回 undefined

所以在实践中,我们的函数没有返回值,我们一般写 void

怎么描述函数的 this

// 这里名称必须为 this
type FnWithThis = (this: {name: string; age: number;}, name: string) => void

const fnWithThis: FnWithThis = function() {
  console.log('hi', this.name)
}

// 此时调用只能显示指定 this
fnWithThiscall({name: 'hh', age: 18}, 'jack')

由于 Function 不够精确,所以 TS 开发者一般用 () => ? 来描述函数
其他对象一般直接用 class 来描述

其他对象

const d: Date = new Date()
const r: RegExp = /ab+c/
const r2: RegExp = new RegExp('ab+c')
const m: Map<string, number> = new Map()
const wm: WeakMap<{name: string}, number> = new WeakMap()
const s: Set<number> = new Set()
const ws: Set<{name: string}, number> = new WeakSet()

any、unknown 是什么?

any 更像是所有的值的集合(也不准确,之后会讲),unknown 和 any 差不多,只是你不收窄类型你就无法使用

never 是什么

可以理解为空集,哪有什么用呢?用来做检查

type A = string & number
// string 和 number 的交集是什么呢?就是 never
// 一般没人会这么写
type B = string | number | boolean
const b:B

if (typeof b === 'string') {
  a.split('')
} else if (typeof b === 'number') {
  a.toFixed(2)
} else if (typeof a === 'boolean') {
  a.valueOf()
} else {
  console.log('没了')
  // 此时这里的 a 就是 never 了,
  // 上面已经把该有的可能都排除了,但是如果让你告诉我这里的 a 是什么类型,怎么解释
  // 为了解释这种类型,所以才有 never
}

关于 JS 类型与 TS 类型的区别

JS 这门语言其实并没有提供类型相关的关键字(如小写的 number、string、boolean),只是提供了 typeof 让我们获取变量的类型,所以我认为 JS 对类型非常不重视。

而 TS 则将 JS 中的类型提升到很高的位置,高到如果你把类型写错了代码就不能通过编译。因此这两门语言中的类型其实没有可比性,只是看起来有重叠部分而已。如果一定要比较,我会这么说:

  1. 粒度不同:在 JS 中的类型 number 不可再细分,而 TS 中的 number 可以看做 1、1.1、2、2.3 等无数个小类型的联合。
  2. 可变性不同:JS 中的变量类型是可变的,一个 number 随时可以变成一个 string;TS 中除了 any,其他类型要么是不可变的,要么就算可变也是有限制的。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容