一. JS/TS中有哪一些数据类型(data type)
- js目前的数据类型有八种
null undefined string number
boolean bigint symbol object
- 可以通过2321分组去记,两个空这一点是js编程语言的特色,其实也可以说是设计缺陷其它语言都是一个空。3个常用的数据类型,string number boolean,接下来bigint 和 symbol放一组,实际开发中也用的不多。最后就是object对象,可以包含Array,Function,Date...,所有复杂一点的对象。
- ts的数据类型,以上所有另外包含
void, never, enum, unknown, any - 再加上两个s自定义类型type和interface,其实也就是三类,第一类是js中有的,第二类是五个自己有的类型,第三类就是自定义类型
二. 如何理解TS的数据类型
-
在js中我们认为的数据类型通常是某个值,而在ts我们应该从集合的角度去理解ts中的类型,举个例子,在js中
let a = 1 -
我们认为a是一个数字,而在ts中
let a: number = 1, 我们认为其中的number这个数字类型代表所有数字的集合,它可以是1|2|-1|1.1|2.2等等所有数字。
三. number和Number,string 和 String, boolean 和 Boolean的区别。
-
拿number去举例,即
let a = 1和let a = new Number(1)的区别,- 区别就是前一种是存粹的0101在内存中表示一个数字,后一种是一个对象它会有toFixed,valueOf等等方法,只有valueOf的时候才返回真正的值。我们通常也不会去用后面的写法,只有在直接使用
1.toFixed()这样的方法时候js会暗箱操作,先let temp = new Number(1),再去把temp.toFix()的值返回,然后删除temp,你可以理解成这是js偷偷摸摸帮你完成了这些操作。
- 区别就是前一种是存粹的0101在内存中表示一个数字,后一种是一个对象它会有toFixed,valueOf等等方法,只有valueOf的时候才返回真正的值。我们通常也不会去用后面的写法,只有在直接使用
-
TS中的Object包含有Number,String和Boolean类型,既然js中我们不用ts中我们也不用,我们也不用大写的Object因为范围太大。
四. 如何在TS里面描述对象的data type
- 用class/constructor描述,这种方式比较死板
const a: Function = () => console.log(1)
- 用type或者interface描述,推荐这种方式,因为灵活
type Person: {
name: string
age: number
}
const a:Person = {
name: 'caikun',
age: 18
}
// 另一种写法,叫做索引签名来描述对象,表示A这个类型是一个对象,它的key必须是string,值必须是value,其中k可以随便写
type A = {
[k: string] : number
}
// 还有一种写法,叫做Record泛型来描述对象和上面写法的含义是一摸一样的
type A2 = Record<string, number>
五. 描述数组对象
type A = string[]
// 等价于
type A = Array<string>
// ts中的远足的写法,下面这种是三元组,面试喜欢问。
type B = [string, string, string]
const error: B = ['A', 'B'] // 会报错,少了一个元素,是一个二元组
// 还可以数组包含数组
- 总结: ts中一般用
Array<?>或者string[]或者[string, number]来描述数组
六. 描述函数对象
// 这里先讲一下最基本的写法,详细写法之后会具体再研究
type FnA = (a: number, b: number) => number;
const a: FnA = () => {
return 123; // 这样没参数也没报错,ts函数的类型检查,对于函数参数来说是松散的,参数少了可以,但是多了会报错
};
// 如果没有返回值,需要用void来表示
type FnReturnVoid = () => void;
const f1: FnReturnVoid = () => {
console.log('hi');
};
// 以上都是写的箭头函数没有this,下面是支持this的例子
type Person = {
name: string;
age: number;
sayHi: FnWithThis;
};
type FnWithThis = (this: Person, name: string) => void;
const sayHi: FnWithThis = function () {
console.log('hi ' + this.name);
};
const x: Person = {
name: '张三',
age: 18,
sayHi: sayHi,
};
x.sayHi('Jack'); // hi 张三
// 等价于
sayHi.call(x, 'Jack')
// 如果你的函数有this,第一点,调用的时候必须显式的传递这个this,第二点,一般而言不能用箭头函数用function。第三点,后面的参数按照除了this之后的开始匹配。
- 总结: Function太不精确,一般用
()=> ?来描述函数
六. 描述其它对象
const d: Date = new Date();
const r: RegExp = /ab+c/;
const r2: RegExp = new RegExp('ab+c');
const m: Map<string, number> = new Map();
m.set('xxx', 2);
const wm: WeakMap<{ name: string }, number> = new WeakMap();
console.log(wm);
const s: Set<number> = new Set();
s.add(123);
const ws: WeakSet<string[]> = new WeakSet();
console.log(ws);
- 总结: 其它对象一般直接用class描述,另外其实这里包含了类型推测的概念,Date,RegExp都可以直接删除,但是Map不行,只要删除之后类型不损失就可以删除。
七. any、unknown是什么?
- 从集合的角度理解,any就是把所有类型并进来
- unknown,就是一个集合,里面是什么不知道,比any好,有机会断言,相当于一个盖住类型的集合,尽量使用unknown
const a: unknown = 1;
console.log(a);
a.toFixed(); // 这样不行。
const b = (a as number).toFixed; // 这样可以,适合这个值是从外部获取的场景,as number相当于就是把盖子揭开
八. never是什么
- never就是空集,不包含任何元素
- 使用场景,用来做检查
type C = string & number;
// const Cake: C = 'ab'; // 会报错误,这个Cake就是never类型,没办法使用,也没人这么用,看得出never就不是给人声明用的
type A = string | number | boolean;
const a: A = 'hello' as any; // 这样写是为了假设不知道a是什么类型
if (typeof a === 'string') {
a.split('');
} else if (typeof a === 'number') {
a.toFixed(2);
} else if (typeof a === 'boolean') {
a.valueOf();
} else {
a.toFixed(); // 会报错,这里的a就是never类型
console.log('没了');
}