1.基础篇
export {}
let test1Arr: string[] = ["12312", "123d"];
// 建议使用下面这种,也方便理解泛型
let test2Arr: Array<string> = ["123", "asdwq"];
// 元组
let tupleType: [string, number] = ["2", 1];
// 枚举 - 无赋值,默认数字型枚举,从零开始,依次递增
enum Score {
BAD, //0
NG, //1
GOOD, //2
GREAT, //3
PERFECT, //4
}
// console.log(Score);
// {
// '0': 'BAD',
// '1': 'NG',
// '2': 'GOOD',
// '3': 'GREAT',
// '4': 'PERFECT',
// BAD: 0,
// NG: 1,
// GOOD: 2,
// GREAT: 3,
// PERFECT: 4
// }
// 字符串类型枚举, 数字型枚举才会具有反向映射
enum Score2 {
BAD,
NG = "Ng",
GOOD = 5, // 5
GREAT, // 6
PERFECT = "Perfect",
}
// console.log(Score2);
// {
// '0': 'BAD',
// '5': 'GOOD',
// '6': 'GREAT',
// BAD: 0,
// NG: 'Ng',
// GOOD: 5,
// GREAT: 6,
// PERFECT: 'Perfect'
// }
/**
* any | unknown | void
*/
// any - 绕过所有类型检查 => 类型检测和编译筛查全部失效
let anyValue: any = "anyValue";
anyValue = false;
anyValue = 123;
let valueString: string = anyValue;
// unknown - 绕过赋值检查 => 禁止更改传递
let unknownValue: unknown;
unknownValue = true;
unknownValue = 123;
unknownValue = "unknownValue";
let value1: unknown = unknownValue; // OK
// let value2: boolean = unknownValue; // NOK
let value3: any = unknownValue; // OK
// void - 声明函数返回值为空
function voidFunction(): void {
console.log("no return");
// 可以这样写return,但是没有返回值
return;
}
// never - 永不返回(返回“从不”的函数不能具有可访问的终结点)
function errorFun(msg: string): never {
throw new Error(msg);
}
function longlongloop(): never {
while (true) {
// ...
}
}
// {} - 描述了一个没有成员的对象
const prop = {};
// prop.a = "zha"; // ERROE
2.type的使用
export {}
/**
* interface
*/
interface Class {
name: string;
time: number;
}
const jiawa: Class = {
name: "加瓦",
time: 1000,
};
// 只读 & 任意
interface Class1 {
readonly name: string;
time: number;
[propName: string]: any;
}
/**
* 交叉类型 &
*/
interface A {
name: D;
}
interface B {
name: E;
}
interface C {
name: F;
}
interface D {
d: boolean;
}
interface E {
e: string;
}
interface F {
f: number;
}
type ABC = A & B & C;
const abc: ABC = {
name: {
d: true,
e: "string",
f: 10,
},
};
// 合并冲突
interface AA {
c: string;
d: string;
}
interface BB {
c: number | string; // 不将其设置成联合类型,下面ab对象的c: "string"会报错
e: string;
}
type AB = AA & BB;
const ab: AB = {
c: "string",
d: "string",
e: "string",
};
/**
* 断言 - 类型的中间执行时声明、转换(过程中和编译器的交流)
*/
const anyValue1: any = "ss";
const anyValLen: number = (<string>anyValue1).length;
const anyValLen1: number = (anyValue1 as string).length;
/**
* 类型守卫 - 保障在语法规定范围做进一步确认业务逻辑
*/
interface Teacher {
name: string;
courses: Array<string>;
}
interface Student {
name: string;
startTime: Date;
}
type Class12 = Teacher | Student;
// 判断属于哪个类型
function startCourse(cls: Class12) {
if ("courses" in cls) {
cls.courses;
} else {
cls.startTime;
}
}
// typeof - 类型分类场景下的身份确认
function startCourse1(name: Class12, score: string | number) {
if (typeof score === "string") {
score;
} else {
score;
}
}
/**
* 泛型
*/
function startClass<T, U>(name: T, score: U): string {
return `${name} + score`;
}
function startClass2<T, U>(name: T, score?: U): T {
return (name + String(score)) as T;
}
3.装饰器(感觉还是没学到这块的精髓使用)
想用装饰器需要在tsconfig.json里改配置
"experimentalDecorators": true
/**
* 类装饰器
*/
function decoratorForPerson(target: any) {
target.age = 18;
}
@decoratorForPerson
class Person1 {
static age: number;
}
console.log(Person1);
// [class Person1] { age: 18 }
/**
* 装饰器组合 - 顺序
*/
function demo1(target: any) {
console.log("demo1");
}
function demo2() {
console.log("demo2");
return (target: any) => {
console.log("demo2里面");
};
}
function demo3() {
console.log("demo3");
return (target: any) => {
console.log("demo3里面");
};
}
function demo4(target: any) {
console.log("demo4");
}
@demo1
@demo2()
@demo3()
@demo4
class Person11 {}
/**
demo2
demo3
demo4
demo3里面
demo2里面
demo1
*/
/**
* 属性装饰器
*/
function fn3(arg: any) {
return (target: any, attr: any) => {
target[attr] = arg;
};
}
class Obj {
@fn3(100)
static age: number;
}
console.log(Obj);
// [class Obj] { age: 100 }
/**
* 方法装饰器
*/
function fn4(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("@", target);
console.log("@@", propertyKey);
console.log("@@@", descriptor);
}
class Person22 {
@fn4
say() {
console.log("say");
}
}
const person22 = new Person22();
person22.say();
/**
@ {}
@@ say
@@@ {
value: [Function: say],
writable: true,
enumerable: false,
configurable: true
}
say
*/
4.TypeScript 中的内置类型
/**
* 内置类型
*/
/**
* Partial - 将类型 T 的所有属性标记为可选属性
*/
/**
* 实现方式
type Partial<T> = {
[P in keyof T]?: T[P];
};
*/
// 用法:Partial<T>
interface Person4 {
name: string;
gender: 0 | 1;
}
const person4: Array<Person4> = [];
// 当我们不需要用到所有属性时
const person4Obj: Partial<Person4> = {
name: "张三",
};
/**
* Required - 将类型 T 的所有属性标记为必选属性
*/
// 实现方式
// type Required<T> = {
// [P in keyof T]-?: T[P];
// };
// -?代表移除?
/**
* Readonly - 将所有属性标记为 readonly, 即不能修改
*/
// 实现方式
// type Readonly<T> = {
// readonly [P in keyof T]: T[P];
// };
/**
* Pick - 从某个类型中过滤出某个或某些属性
*/
// 实现方式
// type Pick<T, K extends keyof T> = {
// [P in K]: T[P];
// };
interface PickTest {
name: string;
age: number;
sex: 0 | 1;
}
type PickTestP = Pick<PickTest, "name" | "age">;
const pickTest: PickTestP = {
name: "张三",
age: 10,
};
/**
* Record - 标记对象的属性(key)或者属性值(value)的类型
*/
// 实现方式
// type Record<K extends keyof any, T> = {
// [P in K]: T;
// };
interface Record1 {
name: string;
age: number;
}
const recordTest: Record<number, Record1> = {
1: {
name: "张三",
age: 10,
},
};
const recordTest1: Record<"name" | "id", string> = {
name: "123",
id: "sx",
};
/**
* Exclude - 移除特定类型中的某个(些)属性
*/
// 实现方式
// type Exclude<T, U> = T extends U ? never : T;
type ExcludeTest4 = Exclude<"a" | "b" | "c", "b" | "c">;
// type ExcludeTest4 = "a"
// Exclude 和 Pick 一起用可用来给“对象”重写某些属性,比如下面是去除某些属性
type FilterPick<T, U extends keyof T> = Pick<T, Exclude<keyof T, U>>;
interface Test4 {
name: string;
age: number;
sex: 0 | 1;
}
interface Test44 extends FilterPick<Test4, "name"> {}
const aaa: Test44 = {
age: 18,
sex: 0,
};
/**
* Extract - Exclude 的反操作,取 T,U 两者的交集属性
*/
// 实现方式
// type Extract<T, U> = T extends U ? T : never;
type ExtractTest = Extract<"a" | "b" | "c", "a" | "b">;
/**
* NonNullable - 排除类型 T 的 null | undefined 属性
*/
// 实现方式
// type NonNullable<T> = T extends null | undefined ? never : T;
/**
* ReturnType -获取函数类型 T 的返回类型
*/
// type ReturnType<T extends (...args: any) => any> = T extends (
// ...args: any
// ) => infer R
// ? R
// : any;
type MyFunction = (a: number, b: string) => boolean;
// 使用 ReturnType 提取返回值类型
type Result = ReturnType<MyFunction>;
// Result 的类型是 boolean,因为 MyFunction 返回值类型是 boolean
tsconfig配置详解
{
"compilerOptions": {
"allowUnreachableCode": true, // 不报告执行不到的代码错误。
"allowUnusedLabels": false, // 不报告未使用的标签错误
"alwaysStrict": false, // 以严格模式解析并为每个源文件生成 "use strict"语句
"baseUrl": ".", // 工作根目录
"experimentalDecorators": true, // 启用实验性的ES装饰器
"jsx": "react", // 在 .tsx文件里支持JSX
"sourceMap": true, // 是否生成map文件
"module": "commonjs", // 指定生成哪个模块系统代码
"noImplicitAny": false, // 是否默认禁用 any
"removeComments": true, // 是否移除注释
"types": [ //指定引入的类型声明文件,默认是自动引入所有声明文件,一旦指定该选项,则会禁用自动引入,改为只引入指定的类型声明文件,如果指定空数组[]则不引用任何文件
"node", // 引入 node 的类型声明
],
"paths": { // 指定模块的路径,和baseUrl有关联,和webpack中resolve.alias配置一样
"src": [ //指定后可以在文件之直接 import * from 'src';
"./src"
],
},
"target": "ESNext", // 编译的目标是什么版本的
"outDir": "./dist", // 输出目录
"declaration": true, // 是否自动创建类型声明文件
"declarationDir": "./lib", // 类型声明文件的输出目录
"allowJs": true, // 允许编译javascript文件。
"lib": [ // 编译过程中需要引入的库文件的列表
"es5",
"es2015",
"es2016",
"es2017",
"es2018",
"dom"
]
},
// 指定一个匹配列表(属于自动指定该路径下的所有ts相关文件)
"include": [
"src/**/*"
],
// 指定一个排除列表(include的反向操作)
"exclude": [
"demo.ts"
],
// 指定哪些文件使用该配置(属于手动一个个指定文件)
"files": [
"demo.ts"
]
}