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