仅供自己学习,如有不对请大佬们斧正,谢谢
安装 typescript
npm i -g typescript
安装 ts-node
npm i -g ts-node
- 就不用tsc 文件名.ts -> node 文件名.js
工程化环境下的TS编译
用 vite 创建一个ts环境
npm create vite@latest my-ts-demo -- --template vanilla-ts cd my-ts-demo npm i npm run dev
类型注解
- 作用: 给一个变量注解一个类型 这个变量只能存放你注解的类型数据 限制了类型
常用基础类型的注解
- 类型就是把类型小写就行了
let count: number;
count = 100;
// count = '100'//不能将类型“string”分配给类型“number”
let name: string = "ts";
name = "123";
let flag: boolean = true;
flag = false;
let id: symbol = Symbol('only');
id = Symbol('only-two');
let un: undefined = undefined;
let nu: null = null;
其它的类型注解
数组
- 方式1: 类型[]
- 方式2:Array<类型>
- 规定数组中只能存放注解后的类型,保证数组中的类型是统一的
// => 只能存放string类型的数组
let userList: string[] = ["mm", 'rr', 'ly'];
let skillList: Array<string> = ["football", "sing song"];
元组
- 可以让同一个数组中按指定规则存在元素,一个萝卜一个坑
- 类型是可以多种的,也有类型限制的
- 数组内部的个数不能多也不能少
- 顺寻必须按照类型定义的顺序书写
let info: [number, string] = [1, "name"];
函数
- 函数 参数 和 返回值的类型注解 [参数 + 返回值]
- 一但进行类型注解之后,实参的传递必须按照类型注解要求的类型来传
- 可以在函数执行之后,方便查看,返回的类型值
function add(a:number, b:number): number {
return a + b
}
let sum = add(1, 2);// let sum: number ts的类型推断
console.log(sum);// 3
// 类型别名的方式
// 只适合函数表达式,可以同时指定 参数 + 返回值
type CustomFn = (a: number, b: number) => number
const plus:CustomFn = (n1, n2) => n1 + n2
console.log(plus(1, 2));//3
// 可选参数
// 所有必选参数必须放在可选参数的前面
function link(a: string, b: string, c?: string): string {
if(c) {
return a + b + c;
}
return a + b;
}
console.log(link('i ', 'love '))//i love
console.log(link('i ', 'love ', 'you'))//i love you
// 没有返回值 void也是 TS中的一种类型
// 表示没有返回值意味着就不用变量去接收这个玩意了
function forArr(arr: string[]): void {
arr.forEach(item => console.log(item))
}
forArr(['1', '2']);
补充:
- 枚举/never/any等类型看看官网
interface接口
- 对一个对象的形状进行描述
- 通常I字母打头,使用大驼峰
- 可选属性 ?:
- 扩展属性
interface IPerson {
name: string,
age: number,
tall?: number,//可选参数
readonly sex : string,//只读属性
say: () => void,
getSkill: (idx: number) => string
[other: string]: any//额外补充
}
const person: IPerson = {
name: 'ly',
age: 18,
sex: '女',
some: 'football',
say() {
console.log('say some')
},
getSkill(idx) {
switch (idx) {
case 1:
return '1';
default:
return '2'
}
}
}
// person.sex = ''//无法分配到 "sex" ,因为它是只读属性
console.log(person.age)
接口继承
- 就是把继承的和自身的属性把必须要的属性都得有
interface Icar {
color: string,
price: number
}
interface IBMW extends Icar{
tall: number,
width: number
}
const bmw: IBMW = {
tall: 130,
width: 250,
color: 'red',
price: 500000
}
console.log(bmw);
总结:
- 作用:描述对象的形状,约束对象的属性方法及类型
泛型
概念: 泛型可以在保证类型安全的前提下,让多个类型一起工作实现类型的复用
- 函数传入一个参数原样返回 [参数类型和返回值类型一致]
function getId(value: string): string {
return value;
}
getId('12');// 只能是string
// 问题这个函数不够通用了,比如我想支持 string/number/boolean/...
// 这种写法参数和返回值的类型都是 T,且T是不固定的,可以在调用的时候在确定T的类型
function getSome<T>(value: T): T {
return value;
}
getSome<string>('1');
getSome(1);
getSome(false);
泛型和接口使用(常用api数据的定义)
- 接口的嵌套
// => 基础的写法
interface IResult {
name: string,
age: number
}
interface IUser {
code: number,
message: string,
result: IResult
}
const user: IUser = {
code: 200,
message: 'success',
result: {
name: 'jly',
age: 18
}
}
interface IUserList {
code: number,
message: string,
result: IResult[]
}
const userLists: IUserList = {
code: 200,
message: 'success',
result: [
{
name: 'jly',
age: 18
},
{
name: 'rr',
age: 19
}
]
}
console.log(user);
console.log(userLists);
- 稍微进阶一点的写法(推荐:项目中还是比较常用的方式)
interface IResult {
name: string,
age: number
}
interface IApi<T> {
code: number,
message: string,
result: T
}
const user1: IApi<IResult> = {
code: 200,
message: 'success',
result: {
name: 'jly',
age: 18
}
}
const userLists1: IApi<IResult[]> = {
code: 200,
message: 'success',
result: [
{
name: 'jly',
age: 18
},
{
name: 'rr',
age: 19
}
]
}
console.log(user1);
console.log(userLists1);
泛型 和 类的配合使用
- 创建一个通用的泛型队列
class Queque<T> {
// data数组中只能存放 T类型的成员
private data: T[];
constructor() {
this.data = [];
}
add(item: T) {
this.data.push(item);
}
pop() {
return this.data.shift();
}
size() {
return this.data.length;
}
isEmpty() {
return this.size() === 0;
}
}
const strQueque = new Queque<string>();
const numQueque = new Queque<number>();
strQueque.add('1');
strQueque.add('2');
strQueque.add('3');
strQueque.isEmpty();
strQueque.size();
strQueque.pop();
numQueque.add(1);
numQueque.add(2);
numQueque.add(3);
numQueque.isEmpty();
numQueque.size();
numQueque.pop();
泛型总结:
- 解决: 类型的复用
- 泛型 + 函数
- 泛型 + 接口
- 泛型 + 类
- 再去看看官网的高级玩法
TS高级类型
联合类型
- 作用: 让一个变量同时支持多种类型的值
- 语法 TypeA | TypeB
let someSth: string|number;
someSth = "this is name";
someSth = 100;
// someSth = true;//不能将类型“boolean”分配给类型“string | number”。
类型别名
- 场景
- 简化复杂类型的使用
- 用来替代interface,做一些对象的shape描述
let value: string | number | boolean;
value = 'this is string'
value = 100
value = true
// => 别名后面再有这种类型的就可以直接复用了
type AType = string | number | boolean;
let valueA: AType;
valueA = 'this is string'
valueA = 100
valueA = true
// => 方式一
interface ISPerson {
name: string,
age: number
}
let p: ISPerson = {
name: 'ly',
age: 18
}
// => 方式二(开发中更常用)
type TypePerson = {
name: string,
age: number
}
let p2: TypePerson = {
name: 'ly',
age: 18
}
交叉类型
- 作用: 多个类型合并成一个类型,被注解的变量需要同时满足多个类型的要求
- 语法 TypeA & TypeB
- 多用于interface接口
interface Size {
width: number
}
interface Color {
bgColor: string
}
let box: Size & Color = {
width: 100,
bgColor: 'red'
}
console.log(box);
字面量类型
- 用处: 经常和我们的联合类型配合使用
- 限制变量是某些中的一个,就比字符串类型更加精确
let str_some = 'this is str some';// let str_some: string
const str_any = 'this is str any';//const str_any: "this is str any"
type Direction = 'left' | 'right' | 'up' | 'down';
function changeDirection(d: Direction) {
console.log(d);
}
changeDirection('left');
// => 限制变量是某些中的一个,就比字符串类型更加精确
// => 其实也可以使用枚举类型
TS泛型工具
- 简化一些泛型操作
- Partial
- 作用: 构造一个新类型 将原有类型中的所有属性都设置为可选,进场和interface配合使用
interface IProps {
name: string,
age: number
}
// 自动全部变成可选属性
type PartialProps = Partial<IProps>
let user: PartialProps = {
name: 'ly'
}
/*
鼠标移上去
type PartialProps = {
name?: string | undefined;
age?: number | undefined;
}
*/
Readonly
- 构造一个新类型, 把所有的属性变成只读属性
interface IProps {
name: string,
age: number
}
// 自动全部变成只读属性
type ReadonlyProps = Readonly<IProps>
/*
鼠标移上去
type ReadonlyProps = {
readonly name: string;
readonly age: number;
}
*/
Pick
- 作用: 构造一个新类型 从原有类型中挑选几个属性
- 就是挑选属性的作用
- 用法: 第一个参数 [接口的类型];第二个参数要的属性 [属性1 | 属性2 |...]
interface IProps {
name: string,
age: number,
id: string
}
// 选则自己想要的属性
type PickProps = Pick<IProps, 'id' | 'name'>
/*
鼠标移上去
type PickProps = {
name: string;
id: string;
}
*/
Record
- 作用: 构造一个对象类型 统一添加多个key 且他们是统一的
type RecordObj = Record<'name' | 'age', string>
let obj: RecordObj = {
name: 'ly',
age: '18'
}
/*
鼠标移上去
type RecordObj = {
name: string;
age: string;
}
*/
类型推论
- 就是不写类型的时候,TS也会给你推导出变量的类型
- 能写类型的地方就自己写,这个看着去吧
类型保护
1.联合类型的类型保护
interface Pig {
eat: boolean,
say: () => void
}
interface Dog {
eat: boolean,
run: () => void
}
function getAnimal(animal: Pig | Dog) {
// 方式1 类型断言,我们来指定类型,TS不要去管了
// ;(animal as Pig).say();
// 方式2 通过in操作符
if('say' in animal) {
animal.say();
}
}
函数的可选参数的类型保护
interface IGPerson {
name: string,
age: number
}
function getPersonInfo(baseName: string, person ?: IGPerson) {
// 做一个判断确保person存在的时候采取读取 name属性
if(person) {
return baseName + person.name;
} else {
return baseName;
}
}
TS编译规则文件 tsconfig.json
- 去官网搜一下常用的配置项目
- 一般不需要修改,除了一些定制化的需求