1. TypeScript 与 JavaScript的区别
- TS 是 JS 的
超集 - 执行环境:node,浏览器都可以直接运行JS,但不能执行TS
- TS需要编译成JS执行,有
编译阶段,JS不需要编译(ES6 -> ES5 那只能叫做转义) - 因为有
类型的加持,TS能带来更好的开发体验,但是写起来也会更难。 - 也因为增加了
类型,所以在执行之前就能杜绝一些不必要的代码错误(比如写错属性)
2. never 类型有什么作用
知名框架Vue作者的回答: TypeScript中的never类型具体有什么用? - 知乎 (zhihu.com)
never是底类型,他表示永远都不应该出现的类型。
interface Foo {
type:'foo'
}
interface Bar {
type:'bar'
}
type All = Foo | Bar
function fn(val:All){
switch(val:type){
case 'foo':
break //这个分支里面 val 的类型会收窄为Foo
case 'bar':
break // 这里的val的类型,会被收窄为Bar
default:
const defaultCheck:never = val
break
}
}
在default 分支里面 val 的类型就被收窄为 never,并且赋值给了一个never的变量。never的作用就是,当哪天All的联合类型增加了类型,但是在函数里面没有增加新的分支,那么编译阶段就会报错。
3. any 与 unknown 的区别
- 两者都是顶级类型,任何类型的值都可以赋值给顶级变量
any类型什么都不做,意思是可以是任何类型。unknown意思是未知(未知可以理解为不知道怎么在unknown集合里面选出对应的类型)的类型。他要求先收窄类型。
const a: unknown = 12
const b: number = a // 报错
unknown 可以看作是所有类型(不包括any,unknown,never,void)的联合类型
const fn = (a:unknown)=>{
if(a instanceof Array){
//array
}else if(isPerson(a)){
// person
}
}
4. enum 的用法
enum Role {
None = 0,
Read = 1 << 0,//0001
Write = 1 << 1, //0010
Delete = 1 << 2, //0100
Manage = Read | Write | Delete //0111
}
const user: { permission: Role } = { permission: 0b10001 }
if ((user.permission & Role.Read) === Role.Read) {
console.log('User can read')
}
枚举类型,一般在枚举的值是数字的时候才好用,其他情况一般不用,因为显得很傻
enum 只能是数字或者字符串
enum Fruit {
Apple='apple',
Banana= 'banana'
}
//可以直接用type 代替
type Fruit = 'apple' | 'banana'
5. type 和 interface 的区别
type 用来给其他类型取一个别名
type FalseLike = false | 0 | '' | null | undefined;
const isFalse: FalseLike = '1' //error
- type 只是给其他类型取一个
别名,interface 是类型声明(interface 会创建新的类型名,type 只是创建类型别名,并没有新创建类型。) - interface 只描述
对象,但是type可以描述所有数据 - type 不可以重新赋值,interface 则会合并类型去并集
- 两者拓展的方式不同,interface使用的是
extends关键字进行拓展,type使用&进行拓展 - type声明类型里面可以使用
in关键字生成映射类型,但是在interface里面不行
type A = {a:number}
type A = {b:string} //Duplicate identifier 'X'.ts(2300)
interface B {
b:number
}
interface B {
c:string
}// 取并集
type Keys = "a" | "b"
interface A {
[key in Keys]: string //这里直接报错
}
type 实现继承: type A = B & C (也叫做交叉类型)
6. 联合类型(union types)
type A = { name: string }
type B = { age: number }
type C = A | B
const c: C = { name: 'foo' }
从数学的角度来看,联合类型取得是A和B的
并集
类型收窄
//类型收窄
const fn = (a: number | string) => {
if (typeof a === 'number') {
a.toFixed()
}
else if (typeof a === 'string') {
a.toUpperCase()
}
else {
throw new Error('Unexpected type')
}
}
局限性:
typeof 数组对象,普通对象,null等都会返回 object
instanceof 不支持基础类型。更重要得一点是不支持TS独有得类型
类型谓词(类型判断)
type Rect = {
width: number
height: number
}
type Circle = {
center: [number, number]
radiuse: number
}
//声明函数来判断,使用 is 关键字
function isRect(x: Rect | Circle): x is Rect {
return 'height' in x && 'width' in x
}
const f1 = (x: Rect | Circle) => {
if (isRect(x)) {
console.log('rect')
} else {
console.log('circle')
}
}
f1({ width: 1, height: 2 })
可辩别联合类型
type Rect = {
kind: 'rect'
width: number
height: number
}
type Circle = {
kind: 'circle'
center: [number, number]
radiuse: number
}
type Shape = Rect | Circle
const f1 = (x: Shape) => {
if (x.kind === 'rect') {
console.log('rect')
} else if (x.kind === 'circle') {
console.log('circle')
} else {
throw new Error('never')
}
}
f1({ kind: 'rect', width: 1, height: 2 })
将对象类型的收窄,转换成基础类型得对比
7.交叉类型(intersection types)
交叉类型可以理解为求两个类型集合的交集。交叉类型常用于有交集的类型。换句话说,当两个类型没有交集的时候,就会得到never的结果
//得到never
type A = string & number //never
//得到never的属性
type A = {
id:string
age:number
}
type B = {
id:number
name:string
}
type C = A & B
const c:C = {
id // never
...
}
8. as const 是干啥用的
告诉ts将变量按照常量来推导
// 这里定义的数组是 readonly 的,不可以对其进行修改
const compoentSize = ['large','middle','small','mini'] as const
//Property 'push' does not exist on type 'readonly ["large", "medium", "small", "mini"]'.ts(2339)
componentSize.push('default');
function sum(...array: number[]) {
const a = [array[0], array[1]] as const
f1(...a)
}
function f1(a: number, b: number) {
return a + b
}