- 一、基础
- 二、进阶
- 全局变量处理
- type和interface的区别
- as
- 单行禁用ts
- Pick
, 将T类型中的K属性挑出来 - Omit
, 将T类型中的K属性排除 - Partial
, 将T类型中的属性都变成可选属性。 - Required
, 将T类型中的属性都变成必选属性 - Extract
, 从类型T中提取所有可以赋值给U的类型,然后构造一个类型 +-这两个关键字用于映射类型中给属性添加修饰符,比如-?就代表将可选属性变为必选,-readonly代表将只读属性变为非只读.- https://mp.weixin.qq.com/s/LlMrYBcvs51-0CSz4pSWDw">学习地址:https://mp.weixin.qq.com/s/LlMrYBcvs51-0CSz4pSWDw
- any和unknow的区别
- undefinde和null的区别
- 在namespace里面使用
- 三、相关学习资料
一、基础
数据类型
布尔类型(boolean)、数字类型(number)、字符串类型(string)、数组类型(array)、元组类型(tuple)、枚举类型(enum)、object类型
任意类型(any)、null 和 undefined、void类型、never类型
HTMLDivElement、HTMLCanvasElement、HTMLSpanElement、HTMLAudioElement、Component
/*** 数据类型* boolean 布尔型* number 数字型* 元组类型(tuple)* 枚举 enum*/let isMarried:boolean = true;let age:number = 10;let firstname:string = '张';let hobbies:string[] = ['smoking','drinking','haire'];let numbers:Array<number> = [4,5,6];let students:Array<object> = [{name:'zfpx1'},{name:'zfpx2'}];let fullname:[string,string,number] = ['张','三',9];let arr2:Array<string|number|boolean> = ['hello',9,true];let arr3:Array<any> = ['hello',9,true];var num:number | undefined;
object类型:用来描述一种非基础类型,所以一般用在类型校验上,比如作为参数类型
declare function create(o: object | null): void;create({ prop: 0 }); // 正确create(null); // 正确create(42); // 错误create("string"); // 错误create(false); // 错误create(undefined); // 错误
枚举
enum 枚举名{标识符[=整型常数],标识符[=整型常数],...标识符[=整型常数],} ;//定义了一个枚举类型的值 性别 ,里面有两个选项 GIRL BOYenum Gender{GIRL='女生',//女孩0BOY='男生'//男孩1}console.log(`李雷是${Gender.BOY},梅梅是${Gender.GIRL}`);//去拼多多买货enum OrderStatus{WaitForPay='等待付款',WaitForSend='等待发货',Sended="已发货",Signed='已签收'}// 如果标识符没有赋值 它的值就是下标
为那些在编程阶段还不清楚类型的变量指定一个类型any
//any 任何类型 任何值 放弃了检查let root = document.getElementById('root');root!.style!.color = 'red';// a的类型可以改变let a:any = 1;a = 'zfpx';// 不知道数组的数据结构let list: any[] = [1, true, "free"];list[1] = 100;
一个变量多种类型
// null undefinedlet x:number|null|undefined;x = 10;x = undefined;x = null;let y:number;//console.log(y);
没有任何类型void, 永不存在的值的类型never
void类型像是与any类型相反,它表示没有任何类型。当一个函数没有返回值时,你通常会见到其返回值类型是 void
never类型表示的是那些永不存在的值的类型。它是其他类型 (包括 null 和 undefined)的子类型,代表从不会出现的值。这意味着声明never的变量只能被never类型所赋值。
function greeting5(name:any):void{console.log('hello',name);return name}greeting5('zfpx');let xxx:never;xxx = (()=>{throw new Error('Wrong')})();let yy:object = {name:'zfpx2'};console.log(yy);
void和never和any区别
/*** any 任何的值* void 是any的反面,不能有任何值* never 永远不会有返回值*/let ak:any = 10;function say():void{}//这个函数一旦开始执行,就永远结束的时候,就进入 死循环function sum():never{while(true){console.log(1);}}function multi():never{throw Error('ok');let a = 10;let b =10;}function divide(a:number,b:number):never|number{return a/b;}divide(10,2);divide(10,0);
函数剩余参数和是否可传的参数
function greeting(name:string):void{console.log('hello',name)}greeting('zfpx');//ts 形参和实参要完全一样function greeting2(name:string,age?:number):void{console.log('hello',name,age)}greeting2('zfpx2');// 赋初始值function ajax(url:string,method:string='GET'){console.log(method,url);}ajax('/user');//剩余参数function sum(...numbers:number[]){return numbers.reduce((val,item)=>{return val+item;},0);}let ret = sum(1,2,3,4,5);console.log(ret);
函数重载
/*** 函数的重载* Java里面呢重载 是指两个或两个以上的函数,参数的个数和类型不一样* TS中的函数重载*///函数的声明 只是用来限制参数的个数和类型/* function attr(val:string):void;function attr(val:number):void;function attr(val:boolean):void; */function attr(val:string|number|boolean):void{if(typeof val =='string'){}else if(typeof val =='number'){}else if(typeof val =='boolean'){}}attr('zfpx');attr(10);attr({});function parse(str:string):any|never{return JSON.parse(str);}let obj = parse('{"name":"zfpx"');console.log(obj);function multi(a:number,b:number):void{return 1;}
class里面
// public 公开的,自己 子类 其它类都能访问// protected 受保护的 自己 子类能访问 但是其它人不能访问// private 私有的 只有自己访问,子类 其它人不能访问// 属性如果不加修饰符 默认就是 公有 (public)class Student extends Parent{public name:stringprotected age:numberprivate money:numberconstructor(name:string,age:number,money:number){super(name, age);//调用父类的构造函数this.money = money;}getMoney(): string{return this.money;}//静态属性static myname='hello'//加上static表示这个属性是静态的属性,是属于类的属性,可以通过类名来调用static getName(){// 这里面不能访问this,因为this指向Student的实例}}interface Animal{name:string;eat(str:string):void;}class Dog implements Animal{name:string;constructor(name:string){this.name=name;}eat(){console.log(this.name+'吃粮食')}}
抽象类
定义:抽象类是可以从中派生其他类的基类。它们可能无法直接实例化。
描述:抽象方法必须包含abstract关键字
区别:抽象类中标记为抽象的方法不包含实现,必须在派生类中实现。
示例说明:抽象类Animal3,抽象方法speak是在Cat3中定义的。Animal3不能有实例,Cat3的实例不能访问speak2方法,可以访问speak方法。
abstract class Animal3{public abstract speak():void;}class Cat3 extends Animal3{speak(){console.log('小猫喵喵喵!');}speak2(){console.log('小猫喵喵喵!');}}
interface接口
接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。 typescrip中的接口类似于java,同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等。
/*** 接口 本质上是一种约束* 约束对象*/interface userInterface{home?:string,height?:number,name:string,age:number}function getUserInfo(user:userInterface):void{console.log(`${user.name} ${user.age} ${user.home}`)}function getVipInfo(user:userInterface):void{console.log(`${user.name} ${user.age}`)}getUserInfo({name:'zfpx',age:10,home:'beijing'});getVipInfo({name:'zfpx',age:10});
通过 keyof 拿到interface对象 key 的类型
interface Person {name: stringage: number}type K1 = keyof Person // "name" | "age"const str2: K1 = 'name'
对函数的参数和返回值进行约束
//如果希望对一个函数的参数和返回值 进行约束interface discount{(price:number):number}let cost:discount = function(price:number):number{return price*.8;}console.log(cost(100));
泛型
//generic typefunction calculate<T>(value:T):T{return value;}//console.log(calculate<string>('zfpx'))//console.log(calculate<number>(1));//类的泛型 如何使用class MyArray<T>{private list:T[] = [];//定义一个私有的属性listadd(value:T){this.list.push(value);}max():T{let ret = this.list[0];for(let i=1;i<this.list.length;i++){if(this.list[i]>ret){ret = this.list[i];}}return ret;}}let arr = new MyArray<string>();arr.add('1');arr.add('2');arr.add('3');console.log(arr.max());
二、进阶
全局变量处理
declare global {namespace util {export let connect: stringexport function date(ms: number | string, fmt: string, countdown?: Boolean): stringexport function gotoUrl(url: string):void}
type和interface的区别
// 1继承的方式不同interface Name {name: string;}interface User extends Name {age: number;}type Name = {name: string;}type User = Name & { age: number };// 泛型(Generics)是对共性的提取(不仅仅是描述)// 接口是一种方面(Aspect)描述
as
interface Doo {bar: number;bas: string;}var foo = {} as Doo;foo = {bas: '23',bar: 23}
单行禁用ts
// tslint:disable-line
Pick, 将T类型中的K属性挑出来
interface Todo {title: string;description: string;completed: boolean;}type TodoPreview = Pick<Todo, 'title' | 'completed'>;const todo: TodoPreview = {title: 'Clean room',completed: false,};
Omit, 将T类型中的K属性排除
interface Todo {title: string;description: string;completed: boolean;}type TodoPreview = Omit<Todo, 'description'>;const todo: TodoPreview = {title: 'Clean room',completed: false,};
Partial, 将T类型中的属性都变成可选属性。
interface Todo {title: string;description: string;}function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {return { ...todo, ...fieldsToUpdate };}const todo1 = {title: 'organize desk',description: 'clear clutter',};const todo2 = updateTodo(todo1, {description: 'throw out trash',});
Required, 将T类型中的属性都变成必选属性
interface Props {a?: number;b?: string;};const obj: Props = { a: 5 }; // OKconst obj2: Required<Props> = { a: 5 }; // Error: property 'b' missing
Extract, 从类型T中提取所有可以赋值给U的类型,然后构造一个类型
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"type T1 = Extract<string | number | (() => void), Function>; // () => void
Exclude
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"type T2 = Exclude<string | number | (() => void), Function>; // string | number
+ -这两个关键字用于映射类型中给属性添加修饰符,比如-?就代表将可选属性变为必选,-readonly代表将只读属性变为非只读.
type Required<T> = { [P in keyof T]-?: T[P] };
学习地址:https://mp.weixin.qq.com/s/LlMrYBcvs51-0CSz4pSWDw
export type PickByValueType<T, ValueType> = Pick<T,{ [Key in keyof T]-?: T[Key] extends ValueType ? Key : never }[keyof T]>;export type OmitByValueType<T, ValueType> = Pick<T,{ [Key in keyof T]-?: T[Key] extends ValueType ? never : Key }[keyof T]>;export type RequiredKeys<T> = {[K in keyof T]-?: {} extends Pick<T, K> ? never : K;}[keyof T];export type OptionalKeys<T> = {[K in keyof T]-?: {} extends Pick<T, K> ? K : never;}[keyof T];export type FunctTypeKeys<T extends object> = {[K in keyof T]-?: T[K] extends Function ? K : never;}[keyof T];export type DeepRequired<T> = {[P in keyof T]-?: T[P] extends object | undefined ? DeepRequired<T[P]> : T[P];};export type DeepPartial<T> = {[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];};
type Naked<T> = T extends boolean ? "Y" : "N";type Wrapped<T> = [T] extends [boolean] ? "Y" : "N";// "N" | "Y"type Distributed = Naked<number | boolean>;
type TypeName<T> = T extends string? "string": T extends number? "number": T extends boolean? "boolean": T extends undefined? "undefined": T extends Function? "function": "object";// 使用上面的TypeName类型别名// "string" | "function"type T1 = TypeName<string | (() => void)>;// "string" | "object"type T2 = TypeName<string | string[]>;// "object"type T3 = TypeName<string[] | number[]>;
any和unknow的区别
相同的是 unknown 和 any 都可接收任意值,不同的是 unknown 的值必须 type check 或 type assertion 后才可使用,否则报错。 推荐用 any 的地方优先用 unknown,因为 unknown 至少类型安全。
function invokeAnything(callback: unknown) {// you cannot operate on `unknown` type// before doing a type check or type assertionif (typeof callback === 'function') {callback();}}invokeAnything(1);
undefinde和null的区别
- undefined是一个没有被分配值的变量- null是一个被人为分配的空值
在namespace里面使用
// 用法1export enum TaskAttribute {TaskId = 0,Progress,TaskType,Duration,Moving = 0x1000,Start,End,UserData = 0x2000,Cookie,Session,}// 用法二class EventManage {constructor(props) {this.name = props.name}}export namespace DownloadEventManage{const eventManage = new EventManage();export function getEventManage() {return eventManage}}
