013 --TypeScript之高级类型

我就是我 2021-11-14 14:48 365阅读 0赞

交叉类型可以简单理解为将多个类型合并成一个类型

  1. function extend<T, U>(first: T, second: U): T & U {
  2. let result = {} as T & U
  3. for(let id in first) {
  4. result[id] = first[id] as any
  5. }
  6. for(let id in second){
  7. if(!result.hasOwnProperty(id)){
  8. result[id] = second[id] as any
  9. }
  10. }
  11. return result
  12. }
  13. //为了编译通过,我们让上述的first[id],second[id]断言成了any
  14. class Person {
  15. constructor(public name: string){
  16. }
  17. }
  18. interface loggable {
  19. log(): void
  20. }
  21. class ConsoleLogger implements loggable {
  22. log(){
  23. }
  24. }
  25. var jim = extend(new Person('jim'), new ConsoleLogger())
  26. //通过extend函数使两个class扩展到一起,称为交叉类型
  27. jim.name
  28. jim.log()

编译后

  1. function extend(first, second) {
  2. var result = {};
  3. for (var id in first) {
  4. result[id] = first[id];
  5. }
  6. for (var id in second) {
  7. if (!result.hasOwnProperty(id)) {
  8. result[id] = second[id];
  9. }
  10. }
  11. return result;
  12. }
  13. //为了编译通过,我们让上述的first[id],second[id]断言成了any
  14. var Person = /** @class */ (function () {
  15. function Person(name) {
  16. this.name = name;
  17. }
  18. return Person;
  19. }());
  20. var ConsoleLogger = /** @class */ (function () {
  21. function ConsoleLogger() {
  22. }
  23. ConsoleLogger.prototype.log = function () {
  24. };
  25. return ConsoleLogger;
  26. }());
  27. var jim = extend(new Person('jim'), new ConsoleLogger());
  28. //通过extend函数使两个class扩展到一起,称为交叉类型
  29. jim.name;
  30. jim.log();

联合类型

  1. function padLeft(value: string, padding: any/*string | number */) {
  2. if(typeof padding === 'number'){
  3. return Array(padding + 1).join(' ') + value
  4. }
  5. if(typeof padding === 'string') {
  6. return padding + value
  7. }
  8. throw new Error(`Expected string or number got ${padding}`)
  9. }
  10. console.log(padLeft('Hello world', 5))// Hello world
  11. console.log(padLeft('Hello world', '123'))//123Hello world
  12. //console.log(padLeft('Hello world', true))//这样写也不会报错,因为padding是any
  13. //什么是联合类型呢,就是如果给padding做约束,就是padding: string | number

联合类型和交叉类型的区别是什么?联合类型是几种之一,交叉类型是几种类型之和

  1. interface Bird {
  2. fly()
  3. layEggs()
  4. }
  5. interface Fish {
  6. swim()
  7. layEggs()
  8. }
  9. function getSmallPet(): Fish | Bird {
  10. return //...
  11. }
  12. let pet = getSmallPet()
  13. pet.layEggs()
  14. //pet.swim()//报错,因为上面声明了是联合类型
  15. //getSmallPet只能是Fish或者Bird
  16. //所以只能调用它们共有的方法

类型保护

上述例子中我们如何判断是哪个类型呢

  1. interface Bird {
  2. fly()
  3. layEggs()
  4. }
  5. interface Fish {
  6. swim()
  7. layEggs()
  8. }
  9. function getSmallPet(): Fish | Bird {
  10. return //...
  11. }
  12. let pet = getSmallPet()
  13. if (isFish(pet)){
  14. pet.swim()
  15. } else {
  16. pet.fly()
  17. }
  18. //类型谓词的类型保护机制
  19. function isFish(pet: Fish | Bird): pet is Fish {
  20. return (pet as Fish).swim !== undefined
  21. }
  22. function isNumber(x: any): x is number {
  23. return typeof x === 'number'
  24. }
  25. function isString(x: any): x is string {
  26. return typeof x === 'string'
  27. }
  28. function padLeft(value: string, padding: string | number){
  29. if (isNumber(padding)) {
  30. return Array(padding + 1).join('') + value
  31. }
  32. if (isString(padding)) {
  33. return padding + value
  34. }
  35. throw new Error(`Expected string or number, got ${padding}`)
  36. }

typeof的类型保护机制

  1. //typeof对基础类型提供类型保护,可以直接推断出值的类型,而不必像上例那样写
  2. //一般 === 和 !==提供保护
  3. //其他的可以用谓词保护
  4. function padLeft(value: string, padding: string | number){
  5. if (typeof padding === 'number') {
  6. return Array(padding + 1).join('') + value
  7. }
  8. if (typeof padding === 'string') {
  9. return padding + value
  10. }
  11. throw new Error(`Expected string or number, got ${padding}`)

instanceof类型保护

  1. class Bird {
  2. fly() {
  3. console.log('bird fly')
  4. }
  5. layEggs(){
  6. console.log('bird lay eggs')
  7. }
  8. }
  9. class Fish {
  10. swim(){
  11. console.log('fish swimming')
  12. }
  13. layEggs(){
  14. console.log('fish lay eggs')
  15. }
  16. }
  17. function getRandomPet(): Fish | Bird {
  18. return Math.random() > 0.5 ? new Bird() : new Fish()
  19. }
  20. let pet = getRandomPet()
  21. if (pet instanceof Bird) {
  22. pet.fly()
  23. }
  24. if (pet instanceof Fish) {
  25. pet.swim()
  26. }

null和undefined

回顾之前的代码

  1. let s = null
  2. s = null
  3. let sn: string | null = 'bar'
  4. sn = null
  5. sn = undefined
  6. //这段代码在编译时是不会出错的
  7. //加上参数 --strictNullChecks会编译出错
  8. function f(x: number, y?: number){
  9. return x + (y || 0)
  10. }
  11. f(1,2)
  12. f(1)
  13. f(1,undefined)
  14. //f(1,null)报错
  15. // 'null' is not assignable to parameter of type 'number | undefined'.

在类中也是一样

  1. class C {
  2. a:number
  3. b?:number//相当于联合类型number | undefined
  4. }
  5. let c = new C()
  6. c.a = 12
  7. c.a = undefined //报错,a为number
  8. c.b = 13
  9. c.b = undefined
  10. c.b = null //报错

null的类型保护和类型断言

  1. function broken(name: string | null ): string {
  2. function postfix(epither: string) {
  3. return name!.charAt(0) + '. the' + epither
  4. }
  5. name = name || 'Bob'
  6. return postfix(name)
  7. }
  8. //上述函数在编译时出错 --strictNullChecks
  9. //ts编译器不知道name是否为null
  10. //我们可以用类型断言方式给name加上!表示name不为null

高级类型之字符串字面量类型

  1. type Easing = 'ease-in' | 'ease-out' | 'ease-in-out'
  2. class UIElement {
  3. animate(dx: number, dy: number,easing: Easing) {
  4. if (easing === 'ease-in') {
  5. //...
  6. } else if (easing === 'ease-out') {
  7. }else if (easing === 'ease-in-out') {
  8. }else {
  9. }
  10. }
  11. }
  12. let button = new UIElement()
  13. button.animate(0, 0, 'ease-in')
  14. //button.animate(0, 0, null)//编译时报错
  15. //Argument of type 'null' is not assignable to parameter of type 'Easing'.

2019-05-30 09:53:16

转载于:https://www.cnblogs.com/ccbest/p/10945225.html

发表评论

表情:
评论列表 (有 0 条评论,365人围观)

还没有评论,来说两句吧...

相关阅读

    相关 TypeScript 高级类型整理

    一、交叉类型(Intersection Types) 交叉类型是奖多个类型合并为一个类型。这往我们可以把多个现有的多种类型叠加成为一种类型,它包含了所需的所有类型的特性。主要