TypeScript_02

interface
interface Cat {
  name: string,
  age: number
}

const c1: Cat = { name: '小白', age: 1 }
const c2: Cat = { name: '小花' }                      // 错误: 缺少 age 属性
const c3: Cat = { name: '小黑', age: 1, sex: '公' } // 错误: 多出 sex 属性
可选属性

如果需要某个属性可选,可以用下面的语法

interface Cat {
  name: string,
  age?: number
}

const c1: Cat = { name: '小白', age: 1 }
const c2: Cat = { name: '小花' }                      // 正确: age 属性可选

可选属性要注意处理 undefined 值

鸭子类型

interface Cat {
  name: string
}

function test(cat: Cat) {
  console.log(cat.name)
}

const c1 = { name: '小白', age: 1 } 
test(c1)

const c1 并没有声明类型为 Cat,但它与 Cat 类型有一样的属性,也可以被当作是 Cat 类型

方法类型
interface Api {
  foo(): void,
  bar(str: string): string
}

function test(api: Api) {
  api.foo()
  console.log(api.bar('hello'))
}

test({
  foo() { console.log('ok') },
  bar(str: string) { return str.toUpperCase() }
})
字面量类型
function printText(s: string, alignment: "left" | "right" | "center") {
  console.log(s, alignment)
}

printText('hello', 'left')
printText('hello', 'aaa') // 错误: 取值只能是 left | right | center
nullish 类型
function test(x?: string | null) {
  console.log(x?.toUpperCase())
}

test('aaa')
test(null)
test()

x?: string | null 表示可能是 undefined 或者是 string 或者是 null

泛型

下面的几个类型声明显然有一定的相似性

interface RefString {
  value: string
}

interface RefNumber {
  value: number
}

interface RefBoolean {
  value: boolean
}

const r1: RefString = { value: 'hello' }
const r2: RefNumber = { value: 123 }
const r3: RefBoolean = { value: true }

可以改进为

interface Ref<T> {
  value: T
}

const r1: Ref<string> = { value: 'hello' }
const r2: Ref<number> = { value: 123 }
const r3: Ref<boolean> = { value: true }
  • 泛型的要点就是 <类型参数>,把【类型】也当作一个变化的要素,像参数一样传递过来,这样就可以派生出结构相似的新类型

  • 函数定义也支持泛型

  • function ref<T>(n: T): Ref<T> {
      return { value: n }
    }
    
    const v1 = ref("hello");     // Ref<string>
    const v2 = ref(123.3333);    // Ref<number>
    
    v1.value.toLocaleLowerCase()
    v2.value.toFixed(2)

    4) 意义

    更好理解框架

    现在越来越多的前端框架采用 typescript,如果懂 typescript 语法,可以更好地阅读框架代码

    以 Map 为例

    const map = new Map<string, string>()
    map
      .set("a", "b")
      .set("c", "d")
    
    map.forEach((value,key,m)=>{
      console.log(value, key)
    })

    注意编译需要 tsc --target es6 .\xxx.ts

  • 更好的提示

    例如,从服务器返回的一段 JSON,如果不用 typescript,则编辑器也不能给出准确的提示

  • interface User {
      name: string,
      age: number
    }
    
    const user: User = JSON.parse(`{ "name":"张三", "age":18 }`)

    5) 类

    关于 TypeScript 与 JavaScript 中的类语法不是重点,class 相关语法只是起到辅助作用,更重要的是前面讲的 interface

    基本语法
    class User {
        name: string;
    
        constructor(name: string) {
            this.name = name
        }
    }
    
    const u = new User('张三')

    其实会被编译成这个样子(默认 --target=es3)

  • var User = /** @class */ (function () {
        function User(name) {
            this.name = name;
        }
        return User;
    }());
    var u = new User('张三');

    所以 js 中的 class,并不等价于 Java 中的 class,它还是基于原型实现的

    只读属性
  • class User {
      readonly name: string;
    
      constructor(name: string) {
          this.name = name
      }
    }
    
    const u = new User('张三')
    u.name = '李四'                // 编译错误

  • readonly 是 typescript 特有的,表示该属性只读

  • 方法
    class User {
      readonly name: string;
    
      constructor(name: string) {
          this.name = name
      }
    
      study() {
        console.log(`[${this.name}]正在学习`)
      }
    }
    
    const u = new User('张三')
    u.study()
    get,set
    class User {
      _name: string;
    
      constructor(name: string) {
        this._name = name
      }
    
      get name() {
        return this._name
      }
    
      set name(name: string) {
        this._name = name
      }
    }
    
    const u = new User('张三')
    console.log(u.name)
    u.name = '李四'
    console.log(u.name)

  • 注意,需要在编译时加上 tsc --target es6 .\xxx.ts 选项

  • es6 等价于 es2015,再此之上还有 es2016 ... es2022

  • 类与接口
    interface User {
      name: string
      study(course: string): void
    }
    
    class UserImpl implements User {
      name: string;
      constructor(name: string) {
        this.name = name
      }
      study(course: string) {
        console.log(`[${this.name}]正在学习[${course}]`)
      }
      foo() { }
    }
    
    const user: User = new UserImpl('张三')
    user.study('Typescript')
    user.foo() // 错误,必须是接口中定义的方法
    继承与接口
    interface Flyable {
      fly(): void
    }
    
    class Animal {
      name: string;
      constructor(name: string) {
        this.name = name
      }
    }
    
    class Bird extends Animal implements Flyable {
      fly() {
        console.log(`${this.name}在飞翔`)
      }
    }
    
    const b: Flyable & Animal = new Bird("小花")
    b.fly()

  • Flyable & Animal 表示变量是 flyable 类型,同时也是 Animal 类型

  • 方法重写
    class Father {
      study(): void {
        console.log(`father study`)
      }
    }
    
    class Son extends Father {  
      study(): void {
        super.study()
        console.log(`son study`)
      }
    }
    
    const f: Father = new Son()
    f.study()//输出son study

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码的翠花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值