banner
banner
banner
NEWS LETTER

TS-接口与类

Scroll down

接口

1
2
3
4
5
6
7
8
interface labelValue {
label : string // 接口里面有一个label属性,且为字符串类型
}
function printLabel2(obj: labelValue) { // 规定传参的类型是这个接口的属性
console.log(obj.label)
}

printLabel2(myObj) // 通过调用传参,只要有一个参数跟接口里面的属性名和类型相同,就会打印

duck-typing特性(鸭子类型)

  • 检验两个比较的对象是否具有相同的属性及类型,b是否包含a
  • 如person与Person的比较,虽然person的属性数量大于Person,但是person具有Person的所有属性且类型相同,所以,检验过程成功
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    interface Person {
    name: string
    age: number
    sex: number
    }

    const person = {
    name: 'schnuffel',
    age: 18,
    sex: 1,
    msg: '1231312312'
    }

    const testFunc = (param: Person) => {
    return param
    }

    testFunc(person)

可选、只读属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface SquareConfig {
color?: string // 可选属性
readonly y: number // 只读属性
}
function createSquare(config: SquareConfig): { color: string; area: number } {
// 规定传参的类型是这个接口的属性,又定义了函数返回的数据类型
let newSquare = {color: "white", area: 100}
if (config.color) {
newSquare.color = config.color
}
return newSquare
}
let mySquare = createSquare({color: "black"})
let p1: SquareConfig = { y: 20 }

只读数组ReadonlyArray:创建后不能被修改

1
2
3
4
let a: number[] = [1, 2, 3, 4]
let ro: ReadonlyArray<number> = a
// 只读数组ro不可以赋值给一个普通数组,要赋值只能断言重写
a = ro as number[] //as把ro从只读数组变为数组类型

额外的属性检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
interface SquareConfig {
color?: string
width?: string
}
function createSquare(config:SquareConfig): {color: string; area: number}{}
let mySquare = createSquare({ colour: "red", width: 100 })
// colour不在createSquare的类型中,报错

解决方法1:类型断言:
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig)

解决方法2:字符串索引签名(最佳):
interface SquareConfig {
color?: string;
width?: number;
[propName: string]: any; // 只要不是color和width,其他的属性都能通过检验
}

解决方法3: 将这个对象赋值给另一个变量
let squareOptions = { colour: "red", width: 100 }
let mySquare = createSquare(squareOptions)

函数类型

1
2
3
4
5
6
7
8
interface SearchFunc {
(source: string, subString: string): boolean
}
// 参数顺序及类型只要与接口中的一样,属性名可不同
mySearch:SearchFunc = function(src: string, sub: string): boolean {
let result = src.search(sub);
return result > -1;
}

可索引的类型

  • ts支持两种索引签名:字符串和数字。可同时使用,但是数字索引的返回值必须是字符串索引返回值类型的子类型
  • 可以设置为只读: readonly [index: number]: string
    1
    2
    3
    interface StringArray {
    [index: number]: string // 定义了一个索引签名[index : number],它的返回类型是string
    }

类类型

实现接口 implements

  • 接口描述了类的公共部分。它不会帮你检查类是否具有某些私有成员。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    interface ClockInterface { // 接口ClockInterface
    currentTime: Date // 方法1
    setTime(d: Date) // 方法2
    }

    class Clock implements ClockInterface { // Clock 实施 ClockInterface
    currentTime: Date; //实例部分检查
    setTime(d: Date) {
    this.currentTime = d // 在Clock类里实现这个方法
    }
    constructor(h: number, m: number) {} //类静态部分,不检查
    }

继承接口 extends

  • 一个接口可以继承多个接口,继承多个接口的接口叫做合成接口
    1
    2
    3
    4
    5
    interface Square extends Shape, PenStroke { // 合成接口
    sideLength: number
    }

    let square = <Square>{} // 定义一个变量去使用合成接口的方法

混合接口:js使用第三方库时用

1
2
3
4
5
6
7
8
9
10
11
12
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}

function getCounter(): Counter {
let counter = <Counter>function (start: number) {} // 作为函数
counter.interval = 123
counter.reset = function () {}
return counter
}

接口继承类型

  • 接口继承类,可继承类的私有属性和protected,但只能被这个类和它的子类实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Control { // 父类
    private state: any
    }
    interface SelectableControl extends Control { // 接口继承父类
    select(): void
    }

    class Button extends Control implements SelectableControl {
    // 子接口继承父类实施接口
    select() { }
    }

    class TextBox extends Control {
    // 子接口继承父类人可以使用接口方法
    select() { }
    }

通过extends的类叫做派生类或子类,而父类叫做基类或超类

修饰符

  • public:默认,公共属性

  • private:私有属性,不能在声明它的类的外部访问。

    • private和protected在比较类型时,只有两个类型都有同样的修饰符,并且该修饰符来自同一基类时,才认为这两个类型是兼容的。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      class Animal {
      private name: string;
      constructor(theName: string) { this.name = theName }
      }

      class Rhino extends Animal {
      constructor() { super("Rhino") } // 使用了父类的构造方法,名字为Rhino
      }
      let animal = new Animal("Goat") // Goat
      let rhino = new Rhino() // Rhino
  • protected:保护属性

    • 不能在声明它的类的外部访问,但派生类中仍然可以访问
    • 构造函数也可以被标记成 protected。这意味着这个类不能在包含它的类外被实例化,但是能被继承
  • readonly:只读修饰符,必须在声明时或构造函数里被初始化。

  • static: 静态属性,只有当前类才有的属性

  • abstract:抽象类

    • 做为其它派生类的基类使用。 它们一般不会直接被实例化
    • 定义的方法必须在派生类中实现,派生类的构造函数必须调用super()
      1
      2
      3
      let department: Department // 允许创建一个对抽象类型的引用
      department = new 子类名() // 允许对一个抽象子类进行实例化和赋值
      department.printName() // 在声明的抽象类中不存在的不可以调用,子类有也不可以

存取器:get和set成对出现

  • get 变量名()
  • set 变量名()
    1
    2
    3
    4
    5
    6
    getToken(): Itoken {
    return Initoken
    },
    setToken( tokenData: Itoken ): Itoken {
    return ( Initoken = { ...Initoken, ...tokenData } )
    }

高级技巧 — 构造函数

  • 类定义会创建两个东西:类的实例类型和一个构造函数。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Greeter {
    static standardGreeting = "Hello,there"
    greeting: string
    constructor(message: string) {
    this.greeting = message
    },
    greet() {
    return "Hello, " + this.greeting
    }
    }

    let greeter: Greeter // 这一行编译为js时是构造函数
    greeter = new Greeter("world") // 创建一个类实例

    let greeterMaker: typeof Greeter = Greeter // 这个变量保存了类构造函数的类型
    greeterMaker.standardGreeting = "Hey there!" // 可以用这个类型中包含的所有静态成员和构造函数

把类当做接口使用:类可以创建出类型,所以在允许使用接口的地方可以使用类

1
2
3
4
5
6
7
8
class Point {
x: number
y: number
}

interface Point3d extends Point {
z: number
}

es5 vs es6 的类区别

  • es6:class类必须new调用,不能直接执行
    • 不存在变量提升
    • 无法遍历它实例原型链上的属性和方法
  • es5:类和普通函数无区别,可以执行
其他文章
cover
TS-模块和命名空间
  • 24/11/01
  • 11:40
  • TypeScript
cover
TS-类型兼容
  • 24/11/01
  • 11:40
  • TypeScript
目录导航 置顶
  1. 1. 接口
    1. 1.1. duck-typing特性(鸭子类型)
    2. 1.2. 可选、只读属性:
    3. 1.3. 只读数组ReadonlyArray:创建后不能被修改
    4. 1.4. 额外的属性检查
    5. 1.5. 函数类型
    6. 1.6. 可索引的类型
  2. 2. 类类型
    1. 2.1. 实现接口 implements
    2. 2.2. 继承接口 extends
    3. 2.3. 混合接口:js使用第三方库时用
    4. 2.4. 接口继承类型
  3. 3.
    1. 3.1. 修饰符
    2. 3.2. public:默认,公共属性
    3. 3.3. private:私有属性,不能在声明它的类的外部访问。
    4. 3.4. protected:保护属性
    5. 3.5. readonly:只读修饰符,必须在声明时或构造函数里被初始化。
    6. 3.6. static: 静态属性,只有当前类才有的属性
    7. 3.7. abstract:抽象类
    8. 3.8. 存取器:get和set成对出现
    9. 3.9. 高级技巧 — 构造函数
    10. 3.10. 把类当做接口使用:类可以创建出类型,所以在允许使用接口的地方可以使用类
    11. 3.11. es5 vs es6 的类区别
请输入关键词进行搜索