一、基础

数据类型

布尔类型(boolean)、数字类型(number)、字符串类型(string)、数组类型(array)、元组类型(tuple)、枚举类型(enum)、object类型
任意类型(any)、null 和 undefined、void类型、never类型
HTMLDivElement、HTMLCanvasElement、HTMLSpanElement、HTMLAudioElement、Component

  1. /**
  2. * 数据类型
  3. * boolean 布尔型
  4. * number 数字型
  5. * 元组类型(tuple)
  6. * 枚举 enum
  7. */
  8. let isMarried:boolean = true;
  9. let age:number = 10;
  10. let firstname:string = '张';
  11. let hobbies:string[] = ['smoking','drinking','haire'];
  12. let numbers:Array<number> = [4,5,6];
  13. let students:Array<object> = [{name:'zfpx1'},{name:'zfpx2'}];
  14. let fullname:[string,string,number] = ['张','三',9];
  15. let arr2:Array<string|number|boolean> = ['hello',9,true];
  16. let arr3:Array<any> = ['hello',9,true];
  17. var num:number | undefined;

object类型:用来描述一种非基础类型,所以一般用在类型校验上,比如作为参数类型

  1. declare function create(o: object | null): void;
  2. create({ prop: 0 }); // 正确
  3. create(null); // 正确
  4. create(42); // 错误
  5. create("string"); // 错误
  6. create(false); // 错误
  7. create(undefined); // 错误

枚举

  1. enum 枚举名{
  2. 标识符[=整型常数],
  3. 标识符[=整型常数],
  4. ...
  5. 标识符[=整型常数],
  6. } ;
  7. //定义了一个枚举类型的值 性别 ,里面有两个选项 GIRL BOY
  8. enum Gender{
  9. GIRL='女生',//女孩0
  10. BOY='男生'//男孩1
  11. }
  12. console.log(`李雷是${Gender.BOY},梅梅是${Gender.GIRL}`);
  13. //去拼多多买货
  14. enum OrderStatus{
  15. WaitForPay='等待付款',
  16. WaitForSend='等待发货',
  17. Sended="已发货",
  18. Signed='已签收'
  19. }
  20. // 如果标识符没有赋值 它的值就是下标

为那些在编程阶段还不清楚类型的变量指定一个类型any

  1. //any 任何类型 任何值 放弃了检查
  2. let root = document.getElementById('root');
  3. root!.style!.color = 'red';
  4. // a的类型可以改变
  5. let a:any = 1;
  6. a = 'zfpx';
  7. // 不知道数组的数据结构
  8. let list: any[] = [1, true, "free"];
  9. list[1] = 100;

一个变量多种类型

  1. // null undefined
  2. let x:number|null|undefined;
  3. x = 10;
  4. x = undefined;
  5. x = null;
  6. let y:number;
  7. //console.log(y);

没有任何类型void, 永不存在的值的类型never

void类型像是与any类型相反,它表示没有任何类型。当一个函数没有返回值时,你通常会见到其返回值类型是 void
never类型表示的是那些永不存在的值的类型。它是其他类型 (包括 null 和 undefined)的子类型,代表从不会出现的值。这意味着声明never的变量只能被never类型所赋值。

  1. function greeting5(name:any):void{
  2. console.log('hello',name);
  3. return name
  4. }
  5. greeting5('zfpx');
  6. let xxx:never;
  7. xxx = (()=>{
  8. throw new Error('Wrong')
  9. })();
  10. let yy:object = {name:'zfpx2'};
  11. console.log(yy);

void和never和any区别

  1. /**
  2. * any 任何的值
  3. * void 是any的反面,不能有任何值
  4. * never 永远不会有返回值
  5. */
  6. let ak:any = 10;
  7. function say():void{}
  8. //这个函数一旦开始执行,就永远结束的时候,就进入 死循环
  9. function sum():never{
  10. while(true){
  11. console.log(1);
  12. }
  13. }
  14. function multi():never{
  15. throw Error('ok');
  16. let a = 10;
  17. let b =10;
  18. }
  19. function divide(a:number,b:number):never|number{
  20. return a/b;
  21. }
  22. divide(10,2);
  23. divide(10,0);

函数剩余参数和是否可传的参数

  1. function greeting(name:string):void{
  2. console.log('hello',name)
  3. }
  4. greeting('zfpx');
  5. //ts 形参和实参要完全一样
  6. function greeting2(name:string,age?:number):void{
  7. console.log('hello',name,age)
  8. }
  9. greeting2('zfpx2');
  10. // 赋初始值
  11. function ajax(url:string,method:string='GET'){
  12. console.log(method,url);
  13. }
  14. ajax('/user');
  15. //剩余参数
  16. function sum(...numbers:number[]){
  17. return numbers.reduce((val,item)=>{
  18. return val+item;
  19. },0);
  20. }
  21. let ret = sum(1,2,3,4,5);
  22. console.log(ret);

函数重载

  1. /**
  2. * 函数的重载
  3. * Java里面呢重载 是指两个或两个以上的函数,参数的个数和类型不一样
  4. * TS中的函数重载
  5. */
  6. //函数的声明 只是用来限制参数的个数和类型
  7. /* function attr(val:string):void;
  8. function attr(val:number):void;
  9. function attr(val:boolean):void; */
  10. function attr(val:string|number|boolean):void{
  11. if(typeof val =='string'){
  12. }else if(typeof val =='number'){
  13. }else if(typeof val =='boolean'){
  14. }
  15. }
  16. attr('zfpx');
  17. attr(10);
  18. attr({});
  19. function parse(str:string):any|never{
  20. return JSON.parse(str);
  21. }
  22. let obj = parse('{"name":"zfpx"');
  23. console.log(obj);
  24. function multi(a:number,b:number):void{
  25. return 1;
  26. }

class里面

  1. // public 公开的,自己 子类 其它类都能访问
  2. // protected 受保护的 自己 子类能访问 但是其它人不能访问
  3. // private 私有的 只有自己访问,子类 其它人不能访问
  4. // 属性如果不加修饰符 默认就是 公有 (public)
  5. class Student extends Parent{
  6. public name:string
  7. protected age:number
  8. private money:number
  9. constructor(name:string,age:number,money:number){
  10. super(name, age);//调用父类的构造函数
  11. this.money = money;
  12. }
  13. getMoney(): string{
  14. return this.money;
  15. }
  16. //静态属性
  17. static myname='hello'
  18. //加上static表示这个属性是静态的属性,是属于类的属性,可以通过类名来调用
  19. static getName(){
  20. // 这里面不能访问this,因为this指向Student的实例
  21. }
  22. }
  23. interface Animal{
  24. name:string;
  25. eat(str:string):void;
  26. }
  27. class Dog implements Animal{
  28. name:string;
  29. constructor(name:string){
  30. this.name=name;
  31. }
  32. eat(){
  33. console.log(this.name+'吃粮食')
  34. }
  35. }

抽象类

定义:抽象类是可以从中派生其他类的基类。它们可能无法直接实例化。
描述:抽象方法必须包含abstract关键字
区别:抽象类中标记为抽象的方法不包含实现,必须在派生类中实现。
示例说明:抽象类Animal3,抽象方法speak是在Cat3中定义的。Animal3不能有实例,Cat3的实例不能访问speak2方法,可以访问speak方法。

  1. abstract class Animal3{
  2. public abstract speak():void;
  3. }
  4. class Cat3 extends Animal3{
  5. speak(){
  6. console.log('小猫喵喵喵!');
  7. }
  8. speak2(){
  9. console.log('小猫喵喵喵!');
  10. }
  11. }

interface接口

接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。 typescrip中的接口类似于java,同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等。

  1. /**
  2. * 接口 本质上是一种约束
  3. * 约束对象
  4. */
  5. interface userInterface{
  6. home?:string,
  7. height?:number,
  8. name:string,
  9. age:number
  10. }
  11. function getUserInfo(user:userInterface):void{
  12. console.log(`${user.name} ${user.age} ${user.home}`)
  13. }
  14. function getVipInfo(user:userInterface):void{
  15. console.log(`${user.name} ${user.age}`)
  16. }
  17. getUserInfo({name:'zfpx',age:10,home:'beijing'});
  18. getVipInfo({name:'zfpx',age:10});

通过 keyof 拿到interface对象 key 的类型

  1. interface Person {
  2. name: string
  3. age: number
  4. }
  5. type K1 = keyof Person // "name" | "age"
  6. const str2: K1 = 'name'

对函数的参数和返回值进行约束

  1. //如果希望对一个函数的参数和返回值 进行约束
  2. interface discount{
  3. (price:number):number
  4. }
  5. let cost:discount = function(price:number):number{
  6. return price*.8;
  7. }
  8. console.log(cost(100));

泛型

  1. //generic type
  2. function calculate<T>(value:T):T{
  3. return value;
  4. }
  5. //console.log(calculate<string>('zfpx'))
  6. //console.log(calculate<number>(1));
  7. //类的泛型 如何使用
  8. class MyArray<T>{
  9. private list:T[] = [];//定义一个私有的属性list
  10. add(value:T){
  11. this.list.push(value);
  12. }
  13. max():T{
  14. let ret = this.list[0];
  15. for(let i=1;i<this.list.length;i++){
  16. if(this.list[i]>ret){
  17. ret = this.list[i];
  18. }
  19. }
  20. return ret;
  21. }
  22. }
  23. let arr = new MyArray<string>();
  24. arr.add('1');
  25. arr.add('2');
  26. arr.add('3');
  27. console.log(arr.max());

二、进阶

全局变量处理

  1. declare global {
  2. namespace util {
  3. export let connect: string
  4. export function date(ms: number | string, fmt: string, countdown?: Boolean): string
  5. export function gotoUrl(url: string):void
  6. }

type和interface的区别

  1. // 1继承的方式不同
  2. interface Name {
  3. name: string;
  4. }
  5. interface User extends Name {
  6. age: number;
  7. }
  8. type Name = {
  9. name: string;
  10. }
  11. type User = Name & { age: number };
  12. // 泛型(Generics)是对共性的提取(不仅仅是描述)
  13. // 接口是一种方面(Aspect)描述

as

  1. interface Doo {
  2. bar: number;
  3. bas: string;
  4. }
  5. var foo = {} as Doo;
  6. foo = {
  7. bas: '23',
  8. bar: 23
  9. }

单行禁用ts

  1. // tslint:disable-line

Pick, 将T类型中的K属性挑出来

  1. interface Todo {
  2. title: string;
  3. description: string;
  4. completed: boolean;
  5. }
  6. type TodoPreview = Pick<Todo, 'title' | 'completed'>;
  7. const todo: TodoPreview = {
  8. title: 'Clean room',
  9. completed: false,
  10. };

Omit, 将T类型中的K属性排除

  1. interface Todo {
  2. title: string;
  3. description: string;
  4. completed: boolean;
  5. }
  6. type TodoPreview = Omit<Todo, 'description'>;
  7. const todo: TodoPreview = {
  8. title: 'Clean room',
  9. completed: false,
  10. };

Partial, 将T类型中的属性都变成可选属性。

  1. interface Todo {
  2. title: string;
  3. description: string;
  4. }
  5. function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
  6. return { ...todo, ...fieldsToUpdate };
  7. }
  8. const todo1 = {
  9. title: 'organize desk',
  10. description: 'clear clutter',
  11. };
  12. const todo2 = updateTodo(todo1, {
  13. description: 'throw out trash',
  14. });

Required, 将T类型中的属性都变成必选属性

  1. interface Props {
  2. a?: number;
  3. b?: string;
  4. };
  5. const obj: Props = { a: 5 }; // OK
  6. const obj2: Required<Props> = { a: 5 }; // Error: property 'b' missing

Extract, 从类型T中提取所有可以赋值给U的类型,然后构造一个类型

  1. type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
  2. type T1 = Extract<string | number | (() => void), Function>; // () => void

Exclude,从类型T中剔除所有可以赋值给U的属性,然后构造一个类型

  1. type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
  2. type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
  3. type T2 = Exclude<string | number | (() => void), Function>; // string | number

+ -这两个关键字用于映射类型中给属性添加修饰符,比如-?就代表将可选属性变为必选,-readonly代表将只读属性变为非只读.

  1. type Required<T> = { [P in keyof T]-?: T[P] };

学习地址:https://mp.weixin.qq.com/s/LlMrYBcvs51-0CSz4pSWDw

  1. export type PickByValueType<T, ValueType> = Pick<
  2. T,
  3. { [Key in keyof T]-?: T[Key] extends ValueType ? Key : never }[keyof T]
  4. >;
  5. export type OmitByValueType<T, ValueType> = Pick<
  6. T,
  7. { [Key in keyof T]-?: T[Key] extends ValueType ? never : Key }[keyof T]
  8. >;
  9. export type RequiredKeys<T> = {
  10. [K in keyof T]-?: {} extends Pick<T, K> ? never : K;
  11. }[keyof T];
  12. export type OptionalKeys<T> = {
  13. [K in keyof T]-?: {} extends Pick<T, K> ? K : never;
  14. }[keyof T];
  15. export type FunctTypeKeys<T extends object> = {
  16. [K in keyof T]-?: T[K] extends Function ? K : never;
  17. }[keyof T];
  18. export type DeepRequired<T> = {
  19. [P in keyof T]-?: T[P] extends object | undefined ? DeepRequired<T[P]> : T[P];
  20. };
  21. export type DeepPartial<T> = {
  22. [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
  23. };
  1. type Naked<T> = T extends boolean ? "Y" : "N";
  2. type Wrapped<T> = [T] extends [boolean] ? "Y" : "N";
  3. // "N" | "Y"
  4. type Distributed = Naked<number | boolean>;
  1. type TypeName<T> = T extends string
  2. ? "string"
  3. : T extends number
  4. ? "number"
  5. : T extends boolean
  6. ? "boolean"
  7. : T extends undefined
  8. ? "undefined"
  9. : T extends Function
  10. ? "function"
  11. : "object";
  12. // 使用上面的TypeName类型别名
  13. // "string" | "function"
  14. type T1 = TypeName<string | (() => void)>;
  15. // "string" | "object"
  16. type T2 = TypeName<string | string[]>;
  17. // "object"
  18. type T3 = TypeName<string[] | number[]>;

any和unknow的区别

相同的是 unknown 和 any 都可接收任意值,不同的是 unknown 的值必须 type check 或 type assertion 后才可使用,否则报错。 推荐用 any 的地方优先用 unknown,因为 unknown 至少类型安全。

  1. function invokeAnything(callback: unknown) {
  2. // you cannot operate on `unknown` type
  3. // before doing a type check or type assertion
  4. if (typeof callback === 'function') {
  5. callback();
  6. }
  7. }
  8. invokeAnything(1);

undefinde和null的区别

  1. - undefined是一个没有被分配值的变量
  2. - null是一个被人为分配的空值

在namespace里面使用

  1. // 用法1
  2. export enum TaskAttribute {
  3. TaskId = 0,
  4. Progress,
  5. TaskType,
  6. Duration,
  7. Moving = 0x1000,
  8. Start,
  9. End,
  10. UserData = 0x2000,
  11. Cookie,
  12. Session,
  13. }
  14. // 用法二
  15. class EventManage {
  16. constructor(props) {
  17. this.name = props.name
  18. }
  19. }
  20. export namespace DownloadEventManage{
  21. const eventManage = new EventManage();
  22. export function getEventManage() {
  23. return eventManage
  24. }
  25. }

三、相关学习资料