Typescript

2020-03-08  本文已影响0人  欢欣的膜笛

安装 Typescript

npm install -g typescript

// 查看 tsc 版本
tsc -v
// 编译 ts 文件
tsc fileName.ts

接口 interface

  1. 约束类型结构、Duck Typing
interface Person {
  readonly id: number;
  name: string;
  age?: number;
}

// 可选参数
function add(x: number, y: number, z?: number): number {
  if (typeof z === 'number') {
    return x + y + z
  } else {
    return x + y
  }
}

// 函数本身的类型
const add2: (x: number, y: number, z?:number) => number = add

// interface 描述函数类型
const sum = (x: number, y: number) => {
  return x + y
}
interface ISum {
  (x: number, y: number): number
}
const sum2: ISum = sum
  1. 类型推论、联合类型、类型断言
// 联合类型
let numberOrString: number | string

// 类型断言 - type assertions
// 这里我们可以用 as 关键字,告诉 typescript 编译器,你没法判断我的代码,但是我本人很清楚,这里我就把它看作是一个 string,你可以给他用 string 的方法。
function getLength(input: string | number): number {
  const str = input as string
  if (str.length) {
    return str.length
  } else {
    const number = input as number
    return number.toString().length
  }
}

// 类型守卫 - type guard
// typescript 在不同的条件分支里面,智能的缩小了范围,这样我们代码出错的几率就大大的降低了。
function getLength2(input: string | number): number {
  if (typeof input === 'string') {
    return input.length
  } else {
    return input.toString().length
  }
}

interface 和 type 的区别

  1. 相同点:都可以描述一个对象或者函数

    • 定义

      interface User { name: string, age: number }
      
      interface SetUser { (name: string, age: number): void }
      
      type User = { name: string, age: number }
      
      type SetUser = (name: string, age: number): void
      
      • extends
      interface Name1 { name: string }
      type Name2 = { name: string }
      
      // interface extends interface
      interface User extends Name1 { age: number }
      
      // interface extends type
      interface User extends Name2 { age: number }
      
      // type 与 type 交叉
      type User = Name2 & { age: number  };
      
      // type 与 interface 交叉
      type User = Name1 & { age: number }
      
  2. 不同点

    • type 可以声明基本类型别名,联合类型,元组等类型,type 语句中还可以使用 typeof 获取实例的类型进行赋值
      // 基本类型别名
      type StringOrNumber = string | number;  
      
      // 联合类型
      interface Dog {
          wong();
      }
      interface Cat {
          miao();
      }
      type Pet = Dog | Cat
      
      // 具体定义数组每个位置的类型
      type PetList = [Dog, Pet]
      
      // 当你想获取一个变量的类型时,使用 typeof
      let div = document.createElement('div');
      type B = typeof div
      
    • interface 能够声明合并
      interface User {
        name: string
        age: number
      }
      
      interface User {
        sex: string
      }
      
      /*
      User 接口为 {
        name: string
        age: number
        sex: string
      }
      */
      

TS——总结函数类型的定义方法

类:定义了一切事物的抽象特点

对象:类的实例
面向对象编程的三大特性:封装、继承、多态
封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,
继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性。
多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。

  1. 基本用法
    class Greeter {
       // 属性
       greeting: string;
    
       // 构造函数,通常用于属性初始化
       constructor(msg: string) {
           this.greeting = msg;
       }
    
       // 方法
       greet() {
           return 'Hello, ' + this.greeting;
       }
     }
    
  2. 继承extends
    • 当父类有构造函数时,子类必须调用(使用super()调用父类构造函数)
    • 子类使用super.XX()访问父类成员
  3. 修饰符:
    • public:成员默认是public,表示成员可以自由访问
    • private:私有的,表示成员只能在当前类内部使用
    • protected:受保护的,表示成员能够在当前类和子类中使用
    • readonly:只读,表示属性只能读取,不能设置,只能在声明时或者构造函数中赋值
    • 参数属性:给构造函数参数加上修饰符,能够同时定义并初始化成员属性
  4. 静态成员:通过static关键字修饰属性、方法,将来通过类名直接访问
  5. 存取器:当获取和设置属性时有额外逻辑时可以使用存储器(gettersetter

函数:

  1. ts中函数的参数是必须的
  2. 函数的可选参数
  3. 函数参数的默认值
  4. 重载
   // 重载
   // 参数数量或者类型或者返回类型不同 函数名却相同
   // 先声明,在实现
   function info(a: { name: string }): string;
   function info(a: string): object;
   function info(a: { name: string } | string): any {
      if (typeof a === "object") {
          return a.name;
       } else {
          return { name: a };
       }
   }
   console.log(info({ name: "tom" }));
   console.log(info("tom"));

范型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

// 使用范型
// T 称为类型变量,是一种特殊的变量,只用于表示类型而不是值
function useGeneric<T>(arg: T): T {
  return arg;
}

// 用法1:完整语法
useGeneric<string>(arg: 'abc');
// 用法2:利用类型推论省略<number>
useGeneric(arg: 1);

// 范型接口
interface Result<T> {
  success: boolean
  data: T
}

// 泛型也可以传入多个值
function swap<T, U>(tuple: [T, U]): [U, T] {
  return [tuple[1], tuple[0]]
}
const result = swap(['string', 123])

// 泛型约束
interface IWithLength {
  length: number;
}
function echoWithLength<T extends IWithLength>(arg: T): T {
  console.log(arg.length)
  return arg
}

echoWithLength('str')
const result3 = echoWithLength({length: 10})
const result4 = echoWithLength([1, 2, 3])

类型别名、字面量、交叉类型

// 类型别名:给类型起一个别名,让它可以更方便的被重用
let sum: (x: number, y: number) => number
const result = sum(1, 2)

type PlusType = (x: number, y: number) => number
let sum2: PlusType
const result2 = sum2(2, 3)

// 支持联合类型
type StrOrNumber = string |number
let result3: StrOrNumber = '123'
result3 = 123

// 字面量
const str: 'name' = 'name'

const number: 1 = 1

type Directions = 'Up' | 'Down' | 'Left' | 'Right'
let toWhere: Directions = 'Down'

// 交叉类型
interface IName {
    name: string
}
type IPerson = IName & { age: number }
let person: IPerson = { name: '123', age: 123 }

// utility types
interface IPerson {
  name: string
  age: number
}

// partial,它可以把传入的类型都变成可选
let viking: IPerson = { name: 'viking', age: 20 }
type IPartial = Partial<IPerson>
let viking2: IPartial = { }

// Omit,它返回的类型可以忽略传入类型的某个属性
type IOmit = Omit<IPerson, 'name'>
let viking3: IOmit = { age: 20 }

模块

装饰器 decorator

装饰器的作用就是在添加装饰器的地方在不改动原有代码的情况下增加额外的功能。Angular框架中装饰器是一个函数。他将元数据添加到类、类成员(属性、方法)和函数参数上。让它们在不需要做任何代码变动的前提下增加额外功能。

  1. 类装饰器:负责把元数据附加到类上,以了解类的设计意图以及这个类是如何工作的

    • @NgModule@NgModule用来描述Angular应用里面的模块(NgModule)的。也就是说NgModule是一个带有@NgModule装饰器的类。@NgModule的参数是一个元数据对象,用于描述如何编译组件的模板,以及如何在运行时创建注入器。
      1. declarations(可声明对象表):那些属于本 NgModule 的组件、指令、管道。
      2. exports(导出表):那些能在其它模块的组件模板中使用的可声明对象的子集。
      3. imports(导入表):那些导出了本模块中的组件模板所需的类的其它模块。
      4. providers:本模块向全局服务中贡献的那些服务的创建器。 这些服务能被本应用中的任何部分使用。(你也可以在组件级别指定服务提供商,这通常是首选方式。)
      5. bootstrap:应用的主视图,称为根组件。它是应用中所有其它视图的宿主。只有根模块才应该设置这个 bootstrap属性。
    • @Directive@Directive修饰的类是指令类。在Angular应用中指令一般用来控制组件(DOM)的某些行为。
    • @Component:声明一个组件时,在组件类上要用@Component装饰器来告知Angular这是一个组件
    • @Pipe@Pipe修饰的类是管道类。在Angular应用中,管道的作用就是传输,可以把一个值通过某种变换成一个新的值。(其实就是对数据做进一步的处理)
    • @Injectable@Injectable修饰的类,表示当前类是一个服务类,可注入。
      @Injectable({
          providedIn: 'root'
      })
      
  2. 属性装饰器:把装饰器添加在属性上,使属性具有额外的一些功能

    • @Input:负责把父组件的数据传递到子组件,然后在子组件里面做相应的处理。
    • @Output:子组件暴露一个EventEmitter属性,当事件发生时,子组件利用该属性emits事件。父组件绑定到这个事件属性,并在事件发生时作出回应。
    • @ViewChild、@ViewChildren:从模板视图中获取匹配的元素
    • @ContentChild、@ContentChildren:用于选择当前组件引用的内容(从ng-content中获取元素) ,一般在自定义组件的时候使用。
    • @Hostbinding:为宿主元素添加属性值(自定义一个指令RainbowDirective,这样所有使用该指令的地方就是宿主元素了.这样可以对添加了该指令的元素做相应的改变)
    • @HostListener:为宿主元素添加事件
  3. 参数装饰器:将装饰器添加在参数上面,一般都是构造函数的参数上。获取注入器里面提供的服务对象。

    • @Inject:用于获取注入器里面注入的token对应的服务实例对象。
    • @Host:获取宿主元素注入器里面注入的对象。父子组件关系不属于宿主关系。所以@Host在父子关系使用不了。

unknown

含义:表示这个值可以是任何值。
用法:在你想用 any 的时候,用 unknown 代替。简单来说,unknown 是一个“严格”版的 any。

never

// 这个 func 返回的就是 never 类型,用到比较少,在类型操作等场景会用到
const func = () => {
    throw new Error()
}

.d.ts

js 文件 + .d.ts 文件 === ts 文件
.d.ts 文件可以让 JS 文件继续维持自己 JS 文件的身份,而拥有 TS 的类型保护。一般我们写业务代码不会用到,但是点击类型跳转一般会跳到 .d.ts 文件。

上一篇下一篇

猜你喜欢

热点阅读