TypeScript高级类型
1. class的基本使用
js提供了class类。TS在此之上 还提供了相应的修饰符 比如:get set
TS中的class,不仅提供了class的语法功能,也作为一种类型存在
class Person {
// 直接定义
age: number
// 有默认值
gender = '男'
}
const p = new Person()
p.age
p.gender
2. 构造函数
class Person {
age:number;
gender:string;
constructor(age:number,gender:string) {
this.age = age
this.gender = gender
}
}
const p = new Person(30,'女')
console.log(p.age,p.gender)
3. 实例方法
class Point {
x = 1
y = 2
scale(n:number):void {
this.x *= n
this.y *= n
}
}
const p = new Point()
p.scale(10)
console.log(p.x,p.y)
4. 继承 extends
class Animal {
move() {
console.log('走两步')
}
}
class Dog extends Animal {
name = '二哈'
bark() {
console.log('旺旺!')
}
}
const d =new Dog()
d.move()
d.bark()
5. 接口
- 通过implements关键字 让class 实现接口。
interface Singable {
sing(): void
}
class Person implements Singable{
sing() {
console.log('hello world')
}
}
6. 类的修饰符
1. public
表示公开的,可以被任何地方访问
class Person {
public move() {
console.log('走两步')
}
}
const p = new Person()
p.move()
2. protected
表示受保护的,仅在声明所在类和子类(非实例)可见
class Person {
protected move() {
console.log('走两步')
}
}
class Man extends Person {
run () {
this.move()
}
}
const p = new Person()
p.move() // 不能访问
3. private
Private: 表示私有的,只在当前类中可见
class Person {
private __move__() {
console.log('走两步')
}
}
class Man extends Person {
run () {
this.__move__() //不能访问
}
}
const p = new Person()
p.__move__() // 不能访问
7. readonly修饰符
表示只读,用来防止在构造函数之外对属性进行赋值
class Person {
readonly age:number = 18
// 只能在constructor中赋值
constructor(age:number) {
this.age = age
}
}
8. 类型兼容性
1. Structural Type System(结构化类型系统)
TS采用的是结构化类型系统
- 在结构化类型系统中,如果两个对象具有相同的形状,认为这是同一个类型
class Point {x:number;y:number}
class Point2D {x:number;y:number}
const p:Point = new Point2D()
2. Nominal Type System (标明类型系统)
C# java 用的是这种
class Point {x:number;y:number}
class Point2D {x:number;y:number}
const p:Point = new Point2D()
// 会报错
9. 交叉类型
类似于接口继承(extends),用于组合多个类型为一个类型(常用于对象类型)
interface Person {name:string}
type PersonDetail = {phone:string} & Person
交叉类型和接口继承对比
- 相同点:都可以实现对象类型的组合。
- 不同点:俩种方式实现类型组合式,对于同名属性直接,处理类型冲突的方式不同
interface A {
fn:(value:number) => string
}
interface B extends A{
fn:(value:string) => string // 会报错
}
////////////////////// 分割线 /////////////////////////
interface A {
fn:(value:number) => string
}
interface B {
fn:(value:string) => string
}
type Contact = A & B
好比 fn:(value:string | number) => string
说明:以上代码,接口继承会报错;交叉类型没有错
10. 泛型
相当于插槽 占位符
// 创建
function id<T>(value:T):T{
return value
}
// 使用
id<number>()
类型约束
// 创建
function id<T extends arrary>(value:T):T{
value.length
return value
}
多个泛型变量的情况
泛型可以有多个 类型变量之间还可以约束
// 创建
function getProp<T,K extends keyof T>(obj:T,key:K){
return obj[key]
}
// 使用
let person = {name:'jack',age:18}
getProp(person,'name')
getProp(['a'],'length')
泛型接口
// 创建
interface IdFunc<T> {
id:(value:T) => Type
ids:() => Type[]
}
// 使用
let obj:IdFunc<number> = {
id(value) {return value},
ids() {return [1]}
}
泛型类
class 也可以配合泛型
// react中使用
interface IState {count: number}
interface IProps {maxLength: number}
class InputCount extends React.Component<IProps,IState> {
state = {
count: 0
}
render() {
return <div>{this.props.maxLength}</div>
}
}
// 创建
class GenericNumber<T>{
defaultValue:T
add: (x:T) => T
}
// 使用
const myNumber = new GenericNumber<number>()
myNumber.defaultValue
索引签名类型
使用场景:当无法确定对象中有哪些属性
interface AnyObject {
[key:string]:number
}
映射类型
- 映射类型基于索引签名类型的
- key in PropKeys 表示key可以是联合类型中的任意一个 类似于 for in(let k in obj)
- 注意:映射类型只能在类型别名中使用,不能在接口中使用
type PropKeys = 'x' | 'y' | 'z'
type TypeObject = {[key in PropKeys]:number}
// in keyof 配合
type Props = {a:number; b:string; c:string}
type Props3 = {[key in keyof Props]: number}
// keyof Props 获取到对象类型所有key变成联合类型 'a' | 'b' | 'c'
// in 遍历了所有 key
索引查询类型
type Props = {a:string,b:string,c:boolean}
type TypeA = Props['a'|'c']
type TypeB = Props[keyof Props]