首页
统计
赞助
留言
关于
更多
友链
壁纸
直播
Search
1
Joe — 一款个人类型Typecho主题
32,764 阅读
2
Joe开源目录程序系统
12,001 阅读
3
Typecho自定义后台编辑器功能
8,394 阅读
4
Joe主题实现自动更新
7,612 阅读
5
Joe主题自定义搭配色教程
4,511 阅读
WEB前端
CSS
React
Vue 2.0
Vue 3.0
JavaScript
TypeScript
Typecho
小程序
苹果CMS
其他
生活
登录
Search
https://78.al
累计撰写
76
篇文章
累计收到
3,760
条评论
首页
栏目
WEB前端
CSS
React
Vue 2.0
Vue 3.0
JavaScript
TypeScript
Typecho
小程序
苹果CMS
其他
生活
页面
统计
赞助
留言
关于
友链
壁纸
直播
搜索到
2
篇与
TypeScript
的结果
2021-04-08
TypeScript
TypeScript快速上手想使用 TypeScript ,需要先安装 Typescript ,安装命令(全局):npm i typescript -gTypeScript是渐进式的,无需懂TypeScript的语法,也可以使用,书写完代码,讲 *.ts 文件编译成普通能识别的 *.js 文件命令:tsc hello.ts原始数据类型const a: string = 'a'; const b: number = 1; // NaN Infinite const c: boolean = true; // false const d: null = null; const f: undefined = undefined; const g: void = undefined; // 联合类型 let a: number | string;unknown & anylet a: any; let b: string; // 将一个any类型赋值给其他类型,允许赋值 b = a; // √ let c: unknown; c = 'asdasd'; // unknown类型不能赋值给其他类型 b = c; // × // 如果就想要把c赋值给b,需要用到以下方式 // 第一种 if(typeof c === "string") b = c // 第二种,类型断言 (<类型>变量) 就相当于 (变量 as 类型) b = <string>c b = c as stringTypeScript中object类型在 typescript 中,定义变量为 object 不仅仅是对象,它表示除原始数据类型的数据,例如函数、数组等const obj1: object = () => {}; const obj2: object = []; const obj3: object = {};而在定义真正对象的时候,可以使用 字面量 方式或 接口 的方式const obj: { age: number; } = { age: 18 };数组类型定义一个变量为数组类型,有两种方式const arr1: Array<number> = [1, 2, 3]; const arr2: number[] = [1, 2, 3]; // demo function sum(...args: number[]) { return args.reduce((prev, current) => prev + current, 0); } sum(1, 2, 3);元组类型const user: [string, number] = ['Joe', 18]; const [_name, _age] = user; // demo const obj = Object.entries({ name: 'Joe', age: 18 }); console.log(obj); // obj返回的就是元组类型枚举类型定义一个枚举使用 enum 关键字,定义后不可以在修改enum STATUS { SUCCESS = 0, FAIL = 1, UNKNOW = 3 } console.log(STATUS.SUCCESS);上方这种方式编译后,会将 STATUS 编译成一个变量,可能会影响到代码的使用,如果不想编译成常量,需要再 enum 前面加上 const 关键字const enum STATUS { SUCCESS = 0, FAIL = 1, UNKNOW = 3 } console.log(STATUS.SUCCESS);函数类型1、函数声明式, ? 表示该值是可有可无的function fn1(a: number, b?: number): number { return 1; } fn1(1);2、函数表达式const fn2 = function (...args: number[]): number { return 1; }; fn2();3、没有返回值function fn3() :void {} fn3();任意类型function stringify(val: any): any { return JSON.stringify(val); } stringify(true);类型断言类型断言有两种方式,第一种方式是采用 as 关键字let _el = document.querySelector('.img'); let el = _el as HTMLImageElement; el.width = 100;第二种方式let _el = <HTMLImageElement>document.querySelector('.img'); _el.width = 1;接口接口的基本使用interface Post { title: string; content: string; } function getDetail(post: Post) { console.log(post.title); console.log(post.content); } getDetail({ title: '1', content: 'aaa' });接口可选属性interface Post { title: string; content: string; summary?: string; } const obj: Post = { title: '11', content: 'asdasd' };接口的动态属性interface Post { title: string; content: string; summary?: string; [key: string]: number | string; } const obj: Post = { title: '11', content: 'asdasd', test: 1 };类class User { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } sayHi(msg: string): void { console.log(`i am ${this.name}`); } }类里面的修饰符class User { // 默认为public public name: string; // 只允许在当前类访问 private age: number; // 只允许在当前和子类访问 protected sex: boolean; // 属性只读,定义后,不能再修改 readonly hobby: string = 'Rap'; constructor(name: string, age: number) { this.name = name; this.age = age; this.sex = true; } sayHi(msg: string): void { console.log(`i am ${this.name}`); } } const Tom = new User('Tom', 18);类与接口interface Eat { eat(food: string): void; } interface Run { run(): void; } // Person去实现 Eat 和 Run 接口 class Person implements Eat, Run { eat(food: string): void {} run() {} } class Animal implements Eat { eat() {} }抽象类abstract class Animal { eat(food: string): void {} abstract run(): void; } class Dog extends Animal { run() {} } // dog会有父类的eat方法,也会有自身的run方法 const dog = new Dog();泛型在定义时,不去指定具体的类型,在调用时,再把类型传递过去// 实现生成数字类型的数组 function createNumberArray(length: number, value: number): number[] { return Array<number>(length).fill(value); } createNumberArray(3, 1); // 实现生成字符串类型的数组 function createStringArray(length: number, value: string): string[] { return Array<string>(length).fill(value); } createStringArray(3, ''); // 利用泛型,根据传递的值,去实现不同的返回类型 function createArray<T>(length: number, value: T): T[] { return Array<T>(length).fill(value); } createArray(3, 1); createArray(3, '');类型声明有时候引入的第三方模块,没有使用类型定义,此时就需要自己去定义类型import { camelCase } from 'lodash'; declare function camelCase(input: string): string; const str = camelCase('asdJdf');
2021年04月08日
540 阅读
6 评论
6 点赞
2021-03-09
TypeScript
Typescript的基本使用Typescript的安装,通过npm全局安装Typescriptnpm install typescript -g编译Typescript的文件,typescript的文件以ts文件格式结尾,需要借助编译器编译成js文件后才可以运行,编译指令tsc xxxx.ts通过上面的方式编译,比较繁琐,因此都会在项目根目录中新建一个 tsconfig.json 的配置文件,用于设置ts文件的编译方式等{ /* * * 包含的路径 * ** 所有目录,包括子目录, * 所有文件 */ "include": ["./src/**/*"], /* * * 不需要被编译的文件目录 * */ "exclude": [], /* * * 编译选项 * */ "compilerOptions": { /* 编译后的目标兼容版本 */ "target": "ES6", /* 模块化规范 */ "module": "ES6", /* 打包后目录 */ "outDir": "./dist", /* 是否编译JS文件 */ "allowJs": false, /* 是否检查JS代码语法规范 */ "checkJs": false, /* 是否移除注释 */ "removeComments": false, /* 不生产编译后的文件 */ "noEmit": false, /* 当有错误时,不生产编译后的文件 */ "noEmitOnError": true, /* 设置编译后的文件为严格模式 */ "alwaysStrict": true, /* 不允许隐式的any类型 */ "noImplicitAny": true, /* 不允许不明确类型的this */ "noImplicitThis": true, /* 严格检查空值 */ "strictNullChecks": true, /* 开启全部严格检查 */ "strict": true // ... } }Typescript的基本语法定义变量的基本类型// 定义数字类型 const num: number = 1; // 定义字符串类型 const str: string = 'joe'; // 定义布尔值类型 const bool: boolean = true注意:null 和 undefined 有且只有1个值,因此声明变量为 null 或 undefined 后就不能再进行赋值操作let _test1: null; let _test2: undefined; _test1 = 1; // × _test2 = 1; // ×如果声明了一个变量,但是没有为这个值赋值,那么这个值默认为 undefinedlet num: number; // num的值为undefined如果既没有声明类型,也没有赋值,那么这个值默认为 any 类型let num; // num被推导为any类型null 和 undefined 在某些情况下,会有隐藏的问题。例如let num: num = 1; num = null; num.toFixed(2); // 这种情况下,编辑器不会报错,但是实际运行是有问题的为了避免出现上面的情形,就需要对 null 和 undefined 开启严格检查模式,开启方式是在 tsconfig.json 文件内加入一行{ "compileOptions": { ... // 设置严格检查 "strictNullChecks": true } }基本类型类型的包装类型在上面定义基本变量的时候,: 后面跟的类型都为小写,小写表示这是一个基本类型的数据,如果大写,那么它表示为基本类型的包装类型,例如let str: string = 'joe' // 定义一个基本类型的字符串 str = new String("1") // × new 出来的字符串,就是个包装类型,不能赋值给简单类型定义变量为对象类型对象内的属性比较少的时候,直接写成行内式const obj: {x: number; y: string} = { x: 1, y: 'joe' }对象内的属性如果多的时候,写成 接口 式// 使用 interface 关键字定义接口 interface MyObject { x: number; y: string; // 任意类型 [prop: string]: any; } // 对象使用接口 const obj: MyObject { x: 1, y: 'joe' }定义变量为数组类型typescript中数组的存储类型必须一致,所以在标注数组类型时,同时要标注数组中存储的数据类型let arr: Array<number> = [1, 2, 3]; // 简写形式:let arr: number[] = ... arr.push('11'); // 错误 arr.push(22); // 正确定义变量为元组类型元组类似数组,但是初始化的个数及对应位置,需要和标注的一致,并且越界数据,必须是标注中的类型之一let arr: [string, number] = ['hello', 2]; arr.push('1'); // 正确 arr.push(1); // 正确 arr.push(true); // 越界数据类型错误定义枚举类型enum HTTP_CODE { SUCCESS = 200, ERROR = 201, URL } HTTP_CODE.URL; // 202枚举类型的注意点:key不能是数字value可以是数字,称为数字类型枚举,如果没有值默认是0枚举值可以省略,如果省略,则:第一个枚举值默认0非第一个枚举值为上一个数字枚举值 + 1枚举值为只读(常量),定义后不可以被修改定义任意类型有时候并不确定这个值到底是什么类型,就可以标注为 any 类型const a: any = 1;any 类型的注意点:一个变量申明了未赋值且未标注情况下,默认为 any任何类型值都可以赋值给any类型any类型有任意属性和方法标注为any类型,意味着放弃对该值的类型检查,同时也放弃了编辑器的提示定义unknow类型unknow类型属于安全版的any类型。例如,由于any可以赋值给任意类型,下面的demo,会报错,并且无法检查到let a: any = '1'; let b: number = 1; b.toFixed(2); b = a; // 无法检测出 b.toFixed(2);换成 unknow 类型let a: unknown = '1'; let b: number = 1; b.toFixed(2); b = a; // 报错。不能将unknow类型赋值给其他类型 b.toFixed(2);使用 unknow 的注意点:unknow类型只能赋值给unknow、anyunknow类型没有任何属性和方法定义函数无返回值类型表示没有任何数据的类型,通常用于标注无返回值函数的返回值类型,函数默认标注类型为 voidfunction fn():void { console.log("joe") }定义函数为never类型当一个函数永远不可能执行 return 的时候,返回的就是 never,与 void 不同,void是执行了 return ,只是没有值,never是不会执行 return,比如抛出错误,导致函数终止执行function fn(): never { throw new Error('error'); }定义函数类型的返回值函数类型可以标注返回值类型、参数的类型,例如function fn(x: number): number { return x; }接口的使用接口的基本使用interface Point { x: number; y: number; } const point: Point = { x: 1, y: 1 }接口可选属性接口可以定义可选的属性,使用 ? 进行标注, ? 表示该值是可选的interface Point { x: number; y: number; z?: string; }接口属性只读接口可以定义只读的属性,使用 readonly进行标注,标注后,表示该属性值不可被修改inteface Point { readonly x: number; readonly y: number; } const point: Point = { x: 1, y: 2 }接口任意类型interface Point { x: number; y: string; [key: string]: any; } const point = { x: 1, y: 'hello', z: 1 }通过接口描述函数// 通过接口定义 interface Func { (e: Event): void; } const fn: Func = (e: Event) => {}; // 直接定义 function fn(el: HTMLElement, callback: (e: Event) => number) {} const div = document.querySelector('div'); fn(div, function () { return 1; });接口重名合并如果写了2个重名的接口,会将这2个接口进行合并interface Point { x: number; y: number; } interface Point { z: string; } const point: Point = { x: 1, y: 1, z: '11' };联合类型如果一个变量可以使用多个类型,可以使用 | 进行分割表示或function fn(el: HTMLElement, attr: string, value: string | number) {} const div = document.querySelector('div'); fn(div, 'a', 1);交叉类型interface O1 { x: number; } interface O2 { y: number; } const o: O1 & O2 = Object.assign({}, { x: 1 }, { y: 2 });注意:上面会报错,说Object上面没有assign方法,此时只需要在tsconfig.json中,添加es的lib库即可解决{ "compilerOptions": { ... "lib": ["ES6"] } }字面量类型在实际使用中,经常会有这种情况,只允许接受几个固定的值,其他的值不允许接受时,就可以使用字面量类型function fn(direction: 'left' | 'right') {} fn('left');类型别名继续上方的字面量类型,如果字面量类型的值过多,此时就应当使用类型别名// 普通使用 type direction = 'left' | 'right'; function fn(direction: direction) {} fn('left'); // 定义函数 type fn = (a: number) => number类型推导在实际开发中,每次定义变量,参数等都要写这些类型,很是麻烦,于是就有了类型推导,会自动根据上下文代码进行推导出类型const a = '111' // 此时,a的类型会自动认定为字符串类型类型断言默认的类型推导范围可能比较广,如果需要缩小范围,就需要使用类型断言const img = <HTMLImageElement>document.querySelector('img'); if (img) { img.src = ''; }函数标注函数标注有以下几种方式/* 第一种 */ function fn(a: number): number { return 1; } fn(1); /* 第二种 */ const fn2: (a: number) => number = function (a) { return 1; }; fn2(2); /* 第三种 */ type CallBack = (num: number) => number; const fn3: CallBack = function (num) { return 1; }; fn3(1); /* 第四种 */ interface Fn { (num: number): number; } let fn4: Fn = function (num) { return 1; }; fn4(2);可选参数function fn(el: HTMLElement, attr: string, val?: number) {} fn(document.querySelector('div'), 'width', 1);参数默认值function fn(attr: 'left' | 'right' = 'left') {} fn('left');剩余参数interface Rest { [key: string]: any; } function fn(target: Array<number>, ...rest: Array<Rest>) {} fn([1]);函数中this标注方式interface T { x: number; fn:(x: number) => void } const obj: T = { x: 1, fn(this: T, x: number){ this.x } }函数重载例如有这样一个例子,以下函数中,第一个参数为dom元素,第二个参数为display或opacity,第三个参数为数字或字符串function setStyle(el: HTMLElement, attr: 'display' | 'opacity', val: 'block' | 'none' | number) { ... }上面的参数这样写没问题,但是想要实现传入display时,第三个值必须是block或none,于是就可以利用函数重载实现function fn(el: HTMLElement, attr: 'display', val: 'block' | 'none'): void function fn(el: HTMLElement, attr: 'opacity', val: number): void function fn(el: HTMLElement, attr: string, val: any){}类类的基本使用class Person { /* 定义在实例上的属性 */ name = '杜恒'; /* 定义在类上的属性 */ static age = 18; /* 定义在实例上的方法 */ static say() { console.log(1); } } const duHeng = new Person() console.log(duHeng) console.log(Person)类的构造器class Dog { name: string; age: number; /* 实例化对象时,会调用这个构造器函数 */ constructor(name: string, age: number) { /* this指向当前实例化出的实例 */ console.log(this); this.name = name; this.age = age; } } const WangCai = new Dog('旺财', 1); const XiaoBai = new Dog('小白', 2); console.log(WangCai); console.log(XiaoBai);在typescript中,定义类的静态属性,使用public关键字,使用后,会自动设置成参数,并且会赋值,上面的写法等同于下面的class Dog { constructor(public name: string, public age: number) { // ... } }类里面的属性修饰符class User { constructor( // 公开属性,默认public public host: number // 可以访问,但是不能修改 readonly id: number, // 只能在内部和子类访问,但是不能被外部修改 protected username: string, // 外部、子类都不可以访问,只有当前能够访问 private password: string ) { } } const user = new User(1, 'Joe', '123') user.id; // 可以访问 user.id = 1; // × 不可以被修改 user.username; // × 不可读 user.password; // × 不可读上面的password设置成私有属性后,外部不可以被访问修改,但是如果就想让外部读取和修改,就需要使用到 寄存器class User { constructor(private _password: string) {} // 用于设置私有属性密码 set password(newPassword: string) { this._password = newPassword; } // 用于获取私有属性密码 get password(): string { return '****'; } } const user = new User('1'); user.password = '111'; user.password类当中的静态成员type FileList = 'gif' | 'png' | 'jpg' class User { // static 定义的属性只存在于类中,不存在于实例中 static readonly FILE_LIST: Array<FileList> = ['gif', 'png'] }抽象类/* * * 声明成抽象的类,无法new这个类 * 抽象类就是专门用来被继承的类 * */ abstract class Component { constructor(public props: any) {} /* 如果声明了方法为抽象的,那么必须声明这个类也是抽象的 */ abstract render(): void; } class SonComponent extends Component { render() {} } new SonComponent(1);规范类,实现类继承多个接口interface Info { getInfo(): string; } class A implements Info { getInfo() { return ''; } }泛型很多时候,标注的具体类型不能确定,因此就需要使用到泛型interface Inter { length: number; } function fn<T extends Inter>(obj: T) { return obj.length; } fn('sdasd');const obj1 = { x: 1, y: 2 } const obj2 = { a: 1, b: 2 } function fn<T>(obj: T, k: keyof T) { return obj[k] } fn<typeof obj1>(obj1, 'x')interface Res<T> { code: number; message?: string; data: T; } interface data { name: string; age: number; } async function getData<U>(url: string) { let response = await fetch(url); let data: Promise<Res<U>> = await response.json(); return data; } (async function () { const res = await getData<data>('/user'); })();
2021年03月09日
629 阅读
2 评论
6 点赞