TypeScript入门 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第9天
为什么选择TS
TS与JS最大的区别就在于TS是静态类型的语言,而JS是动态类型的语言。
在TS中,由于变量定义了类型,这样再多人开发时可维护性大大增强,在编译时期就可以暴露出错误信息,提高开发效率。
TS 包含兼容所有JS的特性,支持调用JS
基本语法
类型
在TS中,变量的声明必须要有类型,否则编译器会报错。
let a: number;
TS支持以下基本类型声明
- number
- string
- boolean
- any
- void
- null
- undefined
- never
- symbol
let a: number = 1;
let b: string = '1';
let c: boolean = true;
let d: any = 1;
let e: void = undefined;
let f: null = null;
let g: undefined = undefined;
let h: never = (() => { throw new Error('error') })();
let i: symbol = Symbol('symbol');
以及可以声明为对象
interface Person {
readonly id: number;
name: string;
age: number;
// 构造时可以不存在
money?: number;
// 任意属性,约束所有对象属性都必须是该属性的子类型
[key: string]: any;
}
let person: Person = {
id: 1,
name: '张三',
age: 18
}
// 会报错 因为定义为readonly只读
person.id = 2;
声明为函数
function add(x: number, y: number): number {
return x + y;
}
// 拆开为const mult: (x: number, y: number) => number和(x, y) => x * y理解
const mult: (x: number, y: number) => number = (x, y) => x * y;
// 也可以通过
interface IMult {
(x: number, y: number): number;
}
const mult2: IMult = (x, y) => x * y;
重载
我们可以通过同名函数而参数不同来实现重载
function getDate(type: 'string', timestamp?: string): string;
function getDate(type: 'date', timestamp?: string): Date;
function getDate(type: 'string' | 'date', timestamp?: string): string | Date {
if (type === 'string') {
return timestamp;
} else {
return new Date(timestamp);
}
}
getDate('date'); // Date
getDate('string', '2018-01-10'); // string
问题代码
interface IGetDate {
(type: 'string', timestamp?: string): string;
(type: 'date', timestamp?: string): Date;
(type: 'string' | 'date', timestamp?: string): string | Date;
}
const getDate2: IGetDate = (type, timestamp) => {
const date = new Date(timestamp);
return type === 'string' ? date.toLocaleString() : date;
}
以上代码会报错,因为我们定义了一个匿名函数,担赋值给了一个IGetDate变量,产生了错误 不能将类型"(type: any,timestamp: any) => string | Date"分配给类型"IGetDate"。不能将类型"string | Date"分配给类型“string”。 不能将类型“Date"分配给类型“string"。ts (2322)
数组
通过类型+[]可以声明数组
/*「类型+方括号」表示*/
type IArr1 = number[];
/* 泛型表示*/
type IArr2 = Array<string | number | Record<string,number>>;
/*元祖表示*/
type IArr3 = [number, number, string,string] ;
/*接口表示*/
interface IArr4 {
[key: number] : any;
}
const arr1: IArr1 = [1,2,3,4,5,6];
const arr2: IArr2 = [1,2,'3','4', { a: 1 }];const arr3: IArr3 = [1,2,'3','4'];
const arr4: IArr4 = [ 'string' , ()=>null,,[]];
补充类型
- 空类型:
() => void - 任意类型:
any - 枚举类型:
enum - 泛型:
type InumArr = Array<number>
泛型
通过泛型我们可以把类型放在尖括号中,这样我们就可以在使用时再指定类型。
function getRepeatArr(target) {
return Array(100).fill(target);
}
type IGetRepeatArr = (target: any) => any[];
type IGetRepeatArrR = <T>(target: T) => T[];
// 泛型接口 & 多泛型
interface IX<T, U> {
key: T;
value: U;
}
// 泛型类
class X<T, U> {
key: T;
value: U;
}
// 泛型别名
type ITypeArr = Array<T>;
// 泛型约束 使用时只能使用number类型或者string类型
type ITypeArr2 = Array<T extends number | string>;
// 通过as关键字,实现类型断言
function test<T extends ITypeArr>(objArr: Array<T>) {
const result = objArr.reduce((pre, cur) => {
return pre + cur;
} , {});
return result as Record<string, T>;
}
字面量
通过 | 来限制必须使用的固定值
// 只能使用下面枚举的值
type IType = 'string' | 'number';
type IOdd = 1 | 3 | 5 | 7 | 9;
高级类型
联合/交叉类型
联合类型
可以通过 | 标识一个值可以是该组合中的一种
// 我们可以选择其中一个进行定义
type IBookList = Array<{
{
type: 'history';
range: string;
} | {
type: 'science';
theme: string;
}
}
交叉类型
可以通过 & 标识一个值需包含该组合中的所有类型
type IBookList = Array<{
type: 'history';
range: string;
} & {
class: string;
type: 'science';
}>
类型保护
通过类型保护,我们可以接收多个类型,但只能访问它们的交集
interface IA {a: 1, a1: 2, c}
interface IB {b: 1, b1: 2, c}
function log(arg: IA | IB) {
// 错误
console.log(arg.a);
// 正确
console.log(arg.c);
}
当访问联合类型时,我们只能访问所有联合类型的交集
类型守卫
通过类型守卫,我们可以指定一个类型的可能性,只有当类型守卫的类型与实际类型相同时,才能访问该属性或方法
interface IA {a: 1, a1: 2, c}
interface IB {b: 1, b1: 2, c}
function getIsIA(arg: IA | IB): arg is IA {
// 当类型守卫的类型与实际类型相同时,才能访问该属性或方法
// !!将类型转换为布尔值再翻转
return !!(arg as IA).a;
}
function getIsIB(arg: IA | IB): arg is IB {
return !!(arg as IB).b;
}
function log(arg: IA | IB) {
if (getIsIA(arg)) {
console.log(arg.a);
} else if (getIsIB(arg)) {
console.log(arg.b);
}
}
实例
function reverse(target: string | Array<any>) {
// type类型保护
if (typeof target === 'string') {
return target.split('').reverse().join('');
}
// instanceof类型保护
if (target instanceof Array) {
return target.reverse();
}
}
function logBook(book: IBookList) {
// 访问交集,类型保护
if (book.type === 'history') {
console.log(book.range);
} else if (book.type === 'science') {
console.log(book.theme);
}
}
工程应用
由于ts并不被原生的js引擎所支持,所以我们需要使用第三方的引擎来支持ts,例如通过webpack进行转换,转为js后再运行
使用TSC进行编译的过程
graph LR
A[Code.ts]--->B[webpack]--->C[TSC]--->D[Code.js]
webpack及vite相关内容代后续笔记完成后补充到这里