likes
comments
collection
share

ts系列(二):interface/type/class/泛型interface 上集谈到用type来自定义一些类型,事

作者站长头像
站长
· 阅读数 26

interface

上集谈到用type来自定义一些类型,事实上也可以通过interface来定义。

// type Person = {
//     firstName:string,
//     lastName:string,
//     age:number
// }

interface Person {
    firstName: string,
    lastName: string,
    age: number
}

let p:Person = {
    firstName : '张',
    lastName:'三',
    age:20
}

interface和type的区别

事实上他们的相似度非常高,但是有一些语法上的差异

  1. type我们又称之为别名,interface接口,语法上来说type可以定义联合类型、交叉类型、对象,而interface用于定义对象
// type 别名
type A = {
  name: string;
  age: number;
};

// type 联合类型
type B = string | number;

// interface
interface C {
  name: string;
  id: number;
}

  1. 继承 type不能继承,interface可以继承interface也可以继承type。当然,也可以一次继承多个。
type Foo = {
    a:string
}

interface A extends Foo{
    b:number   
}


const obj : A = {
    a:'hello',
    b:123
}


// interface 扩展
interface Animal {
  name: string;
}

interface Bird extends Animal {
  honey: boolean;
}

const bird: Bird = {
  name: "bird",     
  honey: true,
};

class关键字不仅可以用作定义构造函数,他也可以当成值类型来用

// 除此之外,class关键字不仅可以用作定义构造函数,他也可以当成值类型来用
class A {
    x: number = 123

    y(): number {
        return 1
    }
}

interface B extends A {
    z: string
}

const b: B = {
    x: 123,
    y: () => { return 1 },
    z: 'hello'
}
  1. 合并 interface可以定义多个相同的名称类型,并且会自动合并但是type别名只能取一个

interface A {
  a: number;
}

interface A {
  b: number;
}

const box: Box = {
  a: 123,
  b: 123, 
};

  1. type中没有this
interface Foo {
    add(num: number): this
}

const f: Foo = {
    add:function(){
        return this
    }
}

我们知道,ts中class不仅可以当构造函数,还可以用于声明类

在js中,这份代码一定是可行的,但是在ts中会说没有name属性,那么我们就想到需要去声明一个类型用于限定一下这个class,但是转头一想,类型都是用来限定值(变量)的,现在拿一个类型来限定类型这合理吗?


class Person{
    constructor(name){
        this.name = name
    }
}

let p = new Person('Tom')

因此,我们应该在自己身上去写类型

class Person{
    readonly age:number;
    name:string
    
    constructor(name:string){
        this.name = name
    }
}


let p = new Person('Tom')
p.name = 'Jerry'
p.age

p.age = 20 // 报错  只读属性

再来看一份代码,ts中的写法和java一样了

interface Country{
    name:string,
    capital:string
}

class Country2{
    name:string
    capital:string
}
class MyCountry implements Country,Country2{
    people:number = 14

    name='China'
    capital='Beijing'
}
let myCountry:MyCountry = new MyCountry()
myCountry.people
myCountry.name
myCountry.capital

interface和类声明的相同类型会合并

class A{
    x:number = 1
}

interface A{
    y:number
}

let a = new A()
a.y

泛型

我们并不知道传递来的参数是什么类型的数组,也不知道返回出来的值是什么类型因此也无法确定函数的类型

function foo(arr:any[]):any {
    return arr[0]
}

因此,我们需要ts自己明白传递的是什么类型,此时我们用到泛型(不在声明的时候确定类型,在调用的时候确定类型)

function foo<T>(arr:T[]):T {
    return arr[0]
}

foo([1,2,3])  // T代表number
foo(['1']) // T代表string



function foo<T>(arr1:T[],arr2:T[]):T[] {
    return arr1.concat(arr2)
}

foo<number|string>([1,2,3],['1','2'])

再看看稍微复杂一点的写法

function myMap<T,U> (arr:T[],f:(arg:T)=>U):U[]{
    return arr.map(f)
}

myMap<string,number>(['1','2','3'],(n)=>parseInt(n))


// 泛型和interface一起用

interface Animal<T,U>{
    name:T
    age:U
}
const an:Animal<string,number> = {
    name:'dog',
    age:2
}

const an2:Animal<number,string> = {
    name:3,
    age: 'cat'
}

小结

注意:我们定义类型,类型名记得大写

interface vs type

  • type: 可以定义一个集合,可以包含各种类型的属性和值,以用来描述对象、函数、联合类型、交叉类型等
    • type不能继承
    • type用=号,interface不用=号,用{}
    • 不仅可以定义对象类型,还可以定义联合、交叉等类型
    • type不能定义相同类型
    • type里面不能用this
  • interface:对象模型,专门用于定义一个对象类型且定义对象和对象内部属性的接口
    • 可以继承type,可以继承interface,可以继承class
    • 多个相同的interface会自动合并

上文还介绍了一些泛型的基本用法,后续将会持续更新。

转载自:https://juejin.cn/post/7410598565863833610
评论
请登录