接口是一系列抽象方法的声明,是一些方法特征的集合。简单来说,接口的作用就是为这些类型命名和为你的代码或第三方代码契约
typescriptinterface Person {
name: string,
age?: number, // 可选属性
readonly height: number, // 只读属性
[index: number]: string, // 索引签名
}
接口可以多继承
tsinterface Student extends Person,Animal {
sno: number
}
typescriptclass Student implements Person {
name: string;
sno: string;
constructor(name: string, sno: string) {
this.name = name;
this.sno = sno;
}
}
function study(p: Person) {
console.log(p);
}
const s = new Student("coder", "001");
study(s);
接口和类型别名的区别
typescriptconst message: 'hello' = 'hello'
默认情况下这么做是没有太大的意义的,但是我们可以将多个类型联合在一起;
typescripttype Alignment = 'right' | 'left' | 'center'
const align: Alignment = 'right'
TSinterface A {
username: string;
age:number
}
let a: keyof A // age | usernmae
keyof
关键字可以获取对象中的所有键类型组成的联合类型。
类型保护允许你使用更小范围下的对象类型
看下图报错,因为n可能是字符串也可能是数字,所以ts会检测错误
通过typeof判断n为string使其可以调用length属性,这就是ts的类型保护
常见的类型保护:
typescriptfunction foo<T>(arg: T): T {
return arg
}
上面的函数可以使用两种方式来调用它:
typescript// 方式一
console.log(foo<string>('hello'))
console.log(foo<number>(1))
// 方式二
console.log(foo('hello'))
console.log(foo(1))
可以传入多个类型:
function foo<T,K>(a1: T, a2: K) { }
typescriptinterface IPerson<T> {
name: T,
friends: T[]
foo: (num: T) => void
}
typescriptclass Person<T> {
x: T
y: T
constructor(x: T, y: T) {
console.log(x, y)
}
}
typescriptinterface ILength {
length: number;
}
function getLength<T extends ILength>(l: T) {
console.log(l.length);
}
getLength("123");
getLength([1, 2, 3]);
类型兼容性用于确定一个类型是否能赋值给其他类型
tslet a: number = 123;
let b: string | number = "hello";
// a = b; // 不能将b赋值给a 因为b有可能是字符串
// b = a; // 可以将a赋值给b
tslet a: { username: string } = { username: "123" };
let b: { username: string; age: number } = { username: "123", age: 123 };
//a = b // success
// b = a // error
可以将已知类型的每个属性都变为可选的或者可读的
TStype A = {
username: string,
age: 24
}
type B<T> = {
[P in keyof T]: T[P] // in 相当于循环遍历了泛型T中的类型
}
type C = B<A> // 别名C和别名A具有相同的类型
Partial<T>
的作用就是将某个类型里的属性全部变为可选项 ? 。
TS// 源码
type Partial<T> = {
[P in keyof T]?: T[P];
};
interface Foo {
name: string
age: number
}
type Bar = Partial<Foo>
// 相当于
type Bar = {
name?: string
age?: number
}
Readonly<T>
的作用是将某个类型所有属性变为只读属性,也就意味着这些属性不能被重新赋值。
TS// 源码
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
interface Foo {
name: string
age: number
}
type Bar = Readonly<Foo>
// 相当于
type Bar = {
readonly name: string
readonly age: number
}
Pick<T, K extends keyof T>
的作用是将某个类型中的子属性挑出来,变成包含这个类型部分属性的子类型。
ts// 源码
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
interface Foo {
name: string;
age?: number;
gender: string;
}
type Bar = Pick<Foo, 'age' | 'gender'>
// 相当于
type Bar = {
age?: number
gender: string
}
const todo: Bar= {
age?: 3,
gender: 男
};
console.log(todo)
Record<K extends keyof any, T>
的作用是将 K
中所有的属性的值转化为 T
类型。
ts// 源码
type Record<K extends keyof any, T> = {
[P in K]: T;
};
type E = Record<"username" | "age", string>;
// 相当于
type E = {
username: string;
age: string;
}
Required<T>
的作用就是将某个类型里的属性全部变为必选项。
tstype Required<T> = {
[P in keyof T]-?: T[P];
};
type A = {
username?: string,
age?: number
}
type B = Required<A>
// 相当于
type B = {
username: string;
age: number;
}
和 Pick
是相反的操作,Omit<T, K extends keyof any>
的作用是使用 T
类型中除了 K
类型的所有属性,来构造一个新的类型。
tstype Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
type A = {
username: string,
age: number
}
type B = Omit<A, 'username'>
//相当于
type B = {
age: number;
}
Exclude<T, U>
的作用是将 T
中的属于 U
的类型移除掉
TStype Exclude<T, U> = T extends U ? never : T;
type A = Exclude<string | number | boolean, string>;
// 相当于
type A = number | boolean
Extract<T, U>
的作用是从 T
中提取出 U
。
tstype Extract<T, U> = T extends U ? T : never;
type A = Extract<string | number | boolean, string>;
// 相当于
type A = string
NonNullable<T>
的作用是用来过滤类型中的 null
及 undefined
类型。
TStype NonNullable<T> = T & {};
type A = NonNullable<string | null | undefined>;
// 相当于
type A = string
Parameters<T>
的作用是用于获得函数的参数类型组成的元组类型。
tstype Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
type Foo = (n: number, m: string) => void;
type a = Parameters<Foo>
// 相当于
type a = [n: number, m: string]
ReturnType<T>
的作用是用于获取函数 T 的返回类型。
TStype ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
type Foo = (n: number, m: string) => number;
type a = ReturnType<Foo>
// 相当于
type a = number
typescriptclass Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
eating() {
console.log(this.name + " is eating");
}
}
const p = new Person("coder", 22);
p.eating();
typescriptclass Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
eating() {
console.log(this.name + " is eating");
}
}
class Student extends Person {
sno: string;
constructor(name: string, age: number, sno: string) {
super(name, age);
this.sno = sno;
}
studying() {
console.log("学号是" + this.sno + "的学生正在学习");
}
}
const s = new Student("yjw", 22, "001");
s.eating();
s.studying();
Student类可以有自己的属性和方法,并且会继承Person的属性和方法;
在构造函数中,通过super来调用父类的构造方法,对父类中的属性进行初始化;
typescriptclass Person {
private name: string;
protected age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
eating() {
console.log(this.name, this.age);
}
}
class Student extends Person {
sno: string;
constructor(name: string, age: number, sno: string) {
super(name, age);
this.sno = sno;
}
}
const p = new Person("coder", 22);
// console.log(p.name); // × 编译错误 属性“name”为私有属性,只能在类“Person”中访问。
// console.log(p.age); // × 编译错误 属性“age”受保护,只能在类“Person”及其子类中访问。
p.eating(); // √
typescriptclass Person {
readonly name:string
constructor(name: string) {
this.name = name
}
}
const p = new Person('coder')
p.name = 'coderyjw' // × 无法分配到 "name" ,因为它是只读属性
在前面一些私有属性我们是不能直接访问的,或者某些属性我们想要监听它的获取(getter)和设置(setter)的过程,
这个时候我们可以使用存取器。
typescriptclass Person {
private _name: string;
constructor(name: string) {
this._name = name;
}
get name(): string {
return this._name;
}
set name(newName) {
this._name = newName;
}
}
const p = new Person("coder");
p.name = 'coderyjw'
console.log(p.name);
用于定义类级别的成员和方法。
typescriptclass Person {
static time: string = "2021-12-26";
}
console.log(Person.time);
typescript// abstract定义的类叫抽象类
// 抽象类不能被实例化,抽象类
// 抽象类中必须要有抽象方法
abstract class Shape {
// abstract定义的函数叫抽象函数
// 抽象方法,必须存在于抽象类中;
// 抽象方法必须被子类实现,否则该类必须是一个抽象类;
abstract getArea(): number;
}
class Circle extends Shape {
r: number;
constructor(r: number) {
super();
this.r = r;
}
getArea(): number {
return this.r * this.r * Math.PI;
}
}
const c = new Circle(5);
console.log(c.getArea());
本文作者:叶继伟
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!