前言
又有两个星期没有写文章了,自从上次拿到了字节的oc之后就开启了我的摆烂生活,现在已经上班两个星期了,先说说感受吧,用我身边其他大厂的朋友总结的七个字就是---------又舒服了,字节哥。不得不说,字节在员工福利这一块真没得说,免费的三餐和下午茶、免费的健身房和住房补贴以及晚上加班到九点半之后的打车报销,虽然杭州这边工区的伙食不是很好,但我还是想说,在字节上班我都要吃胖了,无奈之下只能去健身房收收肚子。
为什么要学TS
两个原因,一呢是因为公司的项目都是ts,不学一下很多代码都看不懂。第二个就是因为实在是太无聊了,实习生刚来没啥事,就分了一个需求给我,然后就是琢磨一下mac,毕竟之前没用过,剩下的时间就是新人培训的刷课和熟悉项目代码,光看代码看得我都要睡着了,所以还是找点事干,就学了一下ts,又能学习又有工资,何乐而不为呢。
常用类型
ts相较于js来说,最显著的地方应该就是类型定义了,这种类型定义的语法和spark有点像,所以我上手起来没那么困难。这篇文章主要分享一些ts里的常用类型,因为其他的知识点我也还没看,摸鱼嘛,肯定还是以摸为主,学为辅,哈哈哈。
基本类型
在ts中,有三种常见的基本类型,就是number、string、boolean。这三种类型在js中已经快见吐了,直接上语法吧。
ts
let n3: number;
function add(number1: number, number2: number) {
return number1 + number2
}
var s4: string;
s4 = 'abc'
let b3: boolean = true;
这里我就不多解释了,语法嘛,硬记就是了,ts完美的兼容了js的语法,所以js的那种写法我就不列举了。
哦,忘记了,ts和js还有一个不一样的地方就是ts会在编译时就找出你的语法错误,而js是在运行时检查,啥叫编译时找错呢,参考一下其他后端语言就知道了,比如C语言,毕竟C语言是所有语言他娘。
数组
数组的声明方法有两种,第一种是常规写法,第二种是泛型,啥是泛型呢,后面再说。ts还新增了一个readonly
关键字,表示只读,用readonly
声明的数组都是只读数组
,只读数组的声明方法也有两种。数组还支持放多种类型的元素,这种类型叫做联合类型
,后面会提到。
ts
const arr1: number[] = [];
const arr2: string[] = [];
const arr3: boolean[] = [];
// 泛型声明
const arr1: Array<number> = [];
const arr2: Array<string> = [];
const arr3: Array<boolean> = [];
// 只读数组
const arr1: readonly string[] = [];
const arr2: ReadonlyArray<string> = [];
// 联合类型的数组
const arr1: (number | string)[] = [];
const arr2: Array<number | string> = [];
枚举(enum)
枚举也是ts独有的数据类型,它和js中的对象有点像,不过也就是有点。枚举有以下类型:数字枚举
、字符串枚举
和异构枚举
。
- 数字枚举
如果没有显式赋值的话,也是枚举的默认赋值行为。枚举的每一项的值都是前一项被赋值的值加1。第一项枚举值是0。
ts
enum Fruit {
apple, // 0
orange, // 1
banana, // 2
}
enum Fruit {
apple = 1, // 1
orange, // 2
banana = 100, // 100
watermelon, // 101
}
// 枚举的值支持动态计算,但动态计算的枚举值下一项必须赋值。
enum Fruit {
apple = getDefaultFruit(),
orange = 1, // 需要赋值
}
- 字符串枚举
字符串枚举的每一项的值都是基本类型string或者另一个字符串枚举的成员,并且枚举不支持动态计算枚举值
ts
enum Direction {
up = 'up',
down = 'down',
left = 'left',
right = 'right'
}
enum Direction_up {
up = Direction.up,
down = getDefault(), // TS Error.含字符串值成员的枚举中不允许使用计算值。
}
- 异构枚举
异构枚举是一种成员既有数字也有字符串成员的枚举类型,每一项字符串成员后定义的成员必须赋初始值,并且不支持动态赋值
ts
enum Fruit {
apple,
orange = 'orange',
banana = 1,
watermelon = get(), // TS Error.含字符串值成员的枚举中不允许使用计算值
}
联合类型(union)
联合类型意味着多种类型合并在一起所产生的一种类型。使用"|"符号来将多种类型组合,给这种类型赋值时,也只能选择其中一种类型的值。在不能确认具体是哪一种类型的情况下,只能访问其所有类型共有的特性,只有显示赋值之后才能访问其独有的方法。
ts
let message: string | number | boolean = 0;
message = 'ok';
message = false;
// 未显示赋值
function run(message: string | number) {
message.toFixed(); // TS Error.类型"string"上不存在属性"toFixed"
}
// 显示赋值后
let message: string | number;
message = ''
message.length;
message = 1;
message.toFixed();
元组(tuple)
元组类型是一种特殊类型的数组。
- 简单元组
声明时就知道数组里有多少元素,每个元素的类型是什么。简单元组类型的长度是固定的。修改每个位置的值时,不能赋与对应位置值的类型不相同的值。
ts
const t1: [string, number] = ['1', 2];
const t2: [number[], readonly number[]] = [[], []];
t1[0] = ''
t2[0] = t2[1]; // TS Error.类型 "readonly number[]" 为 "readonly",不能分配给可变类型 "number[]"。
- 可选元祖
可以利用optional符号"?"来指定元组中的某一项是否是可选的。只有元组的最后一项可以是可选的元素。可选元组的长度不是固定的,会根据可选元素的数量动态变化。
ts
function OptionalTuple1(tuple: [string, number?]) {
tuple.length; // length: 1 | 2
}
function OptionalTuple2(tuple: [string, number, boolean?]) {
tuple.length; // length: 2 | 3
}
- 具名元组
元组的每个值定义了其类型,但使用者并不知道每个值代表什么含义,为了解决这个问题,TypeScript4.0引入了具名元组。支持类似于对象类型的方法给元组每个值都赋予一个名字。
ts
let person: [name: string, age: number];
函数
在ts中函数类型可以有多种定义方式,除了接口函数外每种定义方式都映射了JavaScript中定义函数的方式。其中箭头函数是ES6的新特性,但在TypeScript中,它表示一个函数类型,即任何类型的函数都能赋值给箭头函数类型的值。
ts
// 使用接口声明数类型
interface Hello { (): void; }
// 使用type声明箭头函数类型
type Hello = () => void;
// 使用function关键字声明函数类型
function Hello(): void;
const func1: () => number = () => { return 0; };
const func2: () => number = function () { return 1; };
函数最关注的其实就是两个点,一个是参数,另一个是返回值,ts中还有函数重载
参数常见的有一般参数
、可选参数
和默认参数
ts
function F1(var1: number, var2: string) {}
const F2 = function (var1: number, var2: string) {};
// 可选参数
function F1(var1: number, var2?: string): any;
const F2 = function (var1: number, var2?: string) {};
// 默认参数
function F1(val = '') {}
const F2 = function(var1 = 2) {}
返回值类型通常在参数列表之后定义。与变量类型类似,我们通常不需要返回类型注释,因为 TypeScript 会根据函数的return语句推断函数的返回类型。函数类型有3种定义方式,每种方式都有注明返回值类型的方式
ts
function F1(): number;
interface F2 {
(): string;
}
type F3 = () => boolean;
函数的名称相同,但是函数的参数类型或者个数不同,就是函数的重载。但需要注意的一点是,TypeScript的函数重载是声明式的重载,是方便使用者调用时候查看在不同情况下应该怎么传参。由于JavaScript并不支持重载,所以真正的函数实现时仍然需要根据不同的参数类型,在代码中写入很多分支逻辑,这是不可避免的。
ts
function greet(name: string): string;
function greet(name: string[]): number;
function greet(val: string | string[]): string | number {
if (typeof val === 'string') return val;
return val.length;
}
对象、interface、type和特殊类型
- 对象
对象类型描述了一个具体的JavaScript对象,包含了所有键值对的描述。其实和js差不多,只是多了类型的声明而已。
ts
const object: { a: number, b: string; c: boolean, } = { a: 1, b: '1', c: true }
// 如果不指定属性的值类型,TypeScript默认为any类型,但不推荐这么做。
const object: {
a, // any
b, // any
c, // any
} = { a: 1, b: 1, c: {} }
- interface(接口)
有过java基础的人对这个应该不陌生,因为java里也有接口的定义,接口是声明对象类型的一种方式,接口提供了对象类型的一种命名宏,不能声明基本类型。在接口声明的上下文中可以直接使用该类型赋值给多个对象声明,节省了给每个对象写字面量对象类型的时间。
ts
interface Animal {
name: string;
age: number;
canEat: boolean;
}
const dog: Animal = { name: 'dog', age: 1, canEat: false };
const chicken: Animal = { name: 'chicken', age: 2, canEat: true };
// interface也可以定义函数类型,也可以给函数定义其他额外属性
interface Plus {
(init: number): number;
revoke: (init: number) => number;
}
const plus: Plus = (init: number) => { return init + 1; };
plus.revoke = (init: number) => init - 1;
let result = 1;
result = plus(result);
result = plus.revoke(result);
- type
type本质是给一系列类型起一个别名,类似于用interface关键字给对象类型命名。type和interface在使用上有一些区别,使用type声明类型别名时,需要用"="符号把相应的类型"赋值"给类型别名。
ts
type Point = { x: number; y: number; }
function draw(point: Point) {}
type UserInputValue = string;
type InputValid1 = (input: UserInputValue) => UserInputValue;
// 声明的别名类型是可以换的,如果UserInputValue想换成number,直接换就可以了
type UserInputValue = number;
- 特殊类型
特殊类型常见的有any
、unkonwn
、never
和void
,这里就介绍一下any和never,因为unknown我也没搞懂,我怕误导你们,所以等我搞懂再说,void很好理解,就是函数没有返回值,用来声明空函数。
ts
// any类型的含义是这个值可以是任何其他类型,你可以在any类型的值上进行任何操作
let val: any = 1;
val = '2';
val = () => {}
function main(number1) { // function main(number1: any): any
return number1;
}
// never表示从未观察到的值,或者通过ts类型推断不出来的值,never类型只能赋值给never类型
enum Fruit { apple, orange, }
function checkOverdue(fruit: Fruit) {
if (fruit === Fruit.apple) { }
else if (fruit === Fruit.orange) { }
else { fruit; // fruit: never
}
// never是任何类型的子类型,extends是js的es6新增的关键字,表示继承
type N1 = never extends string ? true : false; // type
N1 = true; type N2 = never extends number ? true : false; // type
N2 = true; type N3 = never extends boolean ? true : false; // type N3 = true;
结语
好久没写文章了,手有点生了,这篇文章虽然内容比较简单,但是却写了好久,金三银四已经过去了,现在已经进入铜五了,近期应该有很多春招补录,最近boss上收到了几个阿里的私信叫我丢简历,如果不是kpi的话应该就是真缺人,所以应该还是有很多岗位的,大家都加油吧