typescript高级编程(一)

typescript 差缺补漏

资料

交叉点类型

交集类型是将多个类型组合为一种的方法,就是多个类型的合并

type LeftType = {
  id: number
  left: string
}

type RightType = {
  id: number
  right: string
}

type IntersectionType = LeftType & RightType

function showType(args: IntersectionType) {
  console.log(args)
}

showType({ id: 1, left: "test", right: "test" })
// Output: {id: 1, left: "test", right: "test"}

联合类型用的比较多

let a:number|string;

通用类型感觉这个很厉害

构造泛型类型,用方括号T作为参数传递

interface GenericType<T> {
  id: number,
  name: T
}

function showType(args: GenericType<string>) {
  console.log(args);
}

function showTypeTwo(args: GenericType<number>) {
  console.log(args);
}

showType({id: 10, name: 'xxx'});
showTypeTwo({id: 10, name: 20});

我以前以为只能用T,今天看了大佬的代码,发现原来T只是一个符号,学习到了

interface GenericType<T,D>{
  id:T,
  name:D
}

function showType(args: GenericType<number, string>) {
  console.log(args);
}
showType({id:20, name: 'ss'});

function showTypeTwo(args: GenericType<number, Array<string>>) {
  
}
showTypeTwo({id:10, name: ['a', 'b', 'c']})

可选

Partial<T>

interface PartialType {
id: number
firstName: string
lastName: string
}

function showType(args: Partial<PartialType>) {
console.log(args)
}

showType({ id: 1 })
// Output: {id: 1}

showType({ firstName: "John", lastName: "Doe" })
// Output: {firstName: "John", lastName: "Doe"}

必传

Required<T>

提供的T需要传所有类型的属性

interface RequiredType {
id: number
firstName?: string
lastName?: string
}

function showType(args: Required<RequiredType>) {
console.log(args)
}

showType({ id: 1, firstName: "John", lastName: "Doe" })
// Output: { id: 1, firstName: "John", lastName: "Doe" }

showType({ id: 1 })
//报错啦

只读

Readonly<T>

T无法使用新值重新分配

interface ReadonlyType {
id: number
name: string
}

function showType(args: Readonly<ReadonlyType>) {
args.id = 4
console.log(args)
}
showType({ id: 1, name: "Doe" })
// error 报错了,他的值都不能被修改
不过下面这样写也不错
interface ReadonlyType {
readonly id: number
name: string
}

忽略

Omit<T,k>

将K从属性T 删除

简单的说就是我输入类型不能带入k,不然会报错

interface PickType {
id: number
firstName: string
lastName: string
}

function showType(args: Omit<PickType, "firstName" | "lastName">) {
console.log(args)
}
showType({id: 12})
// 正常
// 带有firstName 或者 lastName就会报错

挑选

Pick<T,K>

T中要有属性k

interface PickType {
id: number
firstName: string
lastName: string,
name: string
}

function showType(args: Pick<PickType, 'firstName' | 'lastName'>) {
console.log(args);
}

showType({lastName: 'xx', firstName: 'xx'});
showType({lastName: 'xx', firstName: 'xx', id: 12});
// 报错
showType({lastName: 'xx', firstName: 'xx', name:'xx'});
// 报错

仔细的理解了下,就是类型中只能包含firstName 和 lastName,所以可以理解成挑选

k就是你要选择的属性,你可以用|进行分隔选择多个字段

记录

Record<K,T>

将一个类型的属性K映射到另一个类型的属性

interface EmployeeType {
id: number
fullname: string
role: string
}

let employees: Record<number, EmployeeType> = {
0: { id: 1, fullname: "John Doe", role: "Designer" },
1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" },
2: { id: 3, fullname: "Sara Duckson", role: "Developer" },
}
// 0: { id: 1, fullname: "John Doe", role: "Designer" },
// 1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" },
// 2: { id: 3, fullname: "Sara Duckson", role: "Developer" }

映射类型

把每个属性转换为新类型

type StringMap<T> = {
[P in keyof T]: string
}

function showType(arg: StringMap<{ id: number; name: string }>) {
console.log(arg)
}
showType({name:'xx',id:'ss'})
//就是把已经的属性都转成string
showType({ id: 1, name: "Test" })
// 会报错

类型防护

typeof

function showType(x: number | string) {
  if (typeof x === "number") {
    return `The result is ${x + x}`
  }
  throw new Error(`This operation can't be done on a ${typeof x}`)
}

showType("I'm not a number")
// Error: This operation can't be done on a string

showType(7)
// Output: The result is 14

instanceof

class Foo {
  bar() {
    return "Hello World"
  }
}

class Bar {
  baz = "123"
}

function showType(arg: Foo | Bar) {
  if (arg instanceof Foo) {
    console.log(arg.bar())
    return arg.bar()
  }

  throw new Error("The type is not supported")
}

showType(new Foo())
// Output: Hello World

showType(new Bar())
// Error: The type is not supported

in

忽略的点看来我之前的写法没这种好

interface Bookes {
  id: number,
  name: string
}

books: Bookes[] = [
    {id: 1, name: 'Angular'},
    {id: 2, name: 'Typescript'},
    {id: 3, name: 'Javascript'},
    {id: 4, name: 'HTML'}
  ];

发现一个奇怪的!

!只是用来判断null和undefined;

as则可用于变更(缩小或者放大都可以)类型检测范围

as和!用于属性的读取,都可以缩小类型检查范围,都做判空用途时是等价的。只是!具体用于告知编译器此值不可能为空值(null和undefined),而as不限于此

?可用于属性的定义和读取,读取时告诉编译器此值可能为空值(null和undefined),需要做判断。

interface InterArray {
  children?: InterArrayOne
}

interface InterArrayOne {
  name: string,
  age: number
}
export class OneComponent implements OnInit {
  public a: (InterArrayOne & InterArray) [] = [{
    name: 'xx',
    age: 12,
    children: {
      name: 'aaa',
      age: 12
    }
  },
    {
      name: 'aa',
      age: 13,
    },

  ];
  add(): void {
    for (let i = 0; i < this.a.length; i++) {
      console.log(this.a[i]!.children?.name);
    }
  }
  ngOnInit(): void {
    this.add();
  }
}

类型谓词

function isString(x: any): x is string {
  return typeof x === 'string';
}

null!

其实本质上都是null但是加上!会具有语义化些,这个是问大佬们才知道的

undefined! 同理也是false

posted @ 2020-06-18 12:20  猫神甜辣酱  阅读(613)  评论(0编辑  收藏  举报