- 作者:老汪软件技巧
- 发表时间:2024-09-05 10:02
- 浏览量:
interface
上集谈到用type来自定义一些类型,事实上也可以通过interface来定义。
// type Person = {
// firstName:string,
// lastName:string,
// age:number
// }
interface Person {
firstName: string,
lastName: string,
age: number
}
let p:Person = {
firstName : '张',
lastName:'三',
age:20
}
interface和type的区别
事实上他们的相似度非常高,但是有一些语法上的差异
type我们又称之为别名,interface接口,语法上来说type可以定义联合类型、交叉类型、对象,而interface用于定义对象
// type 别名
type A = {
name: string;
age: number;
};
// type 联合类型
type B = string | number;
// interface
interface C {
name: string;
id: number;
}
继承type不能继承,interface可以继承interface也可以继承type。当然,也可以一次继承多个。
type Foo = {
a:string
}
interface A extends Foo{
b:number
}
const obj : A = {
a:'hello',
b:123
}
// interface 扩展
interface Animal {
name: string;
}
interface Bird extends Animal {
honey: boolean;
}
const bird: Bird = {
name: "bird",
honey: true,
};
class关键字不仅可以用作定义构造函数,他也可以当成值类型来用
// 除此之外,class关键字不仅可以用作定义构造函数,他也可以当成值类型来用
class A {
x: number = 123
y(): number {
return 1
}
}
interface B extends A {
z: string
}
const b: B = {
x: 123,
y: () => { return 1 },
z: 'hello'
}
合并interface可以定义多个相同的名称类型,并且会自动合并但是type别名只能取一个
interface A {
a: number;
}
interface A {
b: number;
}
const box: Box = {
a: 123,
b: 123,
};
type中没有this
interface Foo {
add(num: number): this
}
const f: Foo = {
add:function(){
return this
}
}
类
我们知道,ts中class不仅可以当构造函数,还可以用于声明类
在js中,这份代码一定是可行的,但是在ts中会说没有name属性,那么我们就想到需要去声明一个类型用于限定一下这个class,但是转头一想,类型都是用来限定值(变量)的,现在拿一个类型来限定类型这合理吗?
class Person{
constructor(name){
this.name = name
}
}
let p = new Person('Tom')
因此,我们应该在自己身上去写类型
class Person{
readonly age:number;
name:string
constructor(name:string){
this.name = name
}
}
let p = new Person('Tom')
p.name = 'Jerry'
p.age
p.age = 20 // 报错 只读属性
再来看一份代码,ts中的写法和java一样了
interface Country{
name:string,
capital:string
}
class Country2{
name:string
capital:string
}
class MyCountry implements Country,Country2{
people:number = 14
name='China'
capital='Beijing'
}
let myCountry:MyCountry = new MyCountry()
myCountry.people
myCountry.name
myCountry.capital
interface和类声明的相同类型会合并
class A{
x:number = 1
}
interface A{
y:number
}
let a = new A()
a.y
泛型
我们并不知道传递来的参数是什么类型的数组,也不知道返回出来的值是什么类型因此也无法确定函数的类型
function foo(arr:any[]):any {
return arr[0]
}
因此,我们需要ts自己明白传递的是什么类型,此时我们用到泛型(不在声明的时候确定类型,在调用的时候确定类型)
function foo(arr:T[]):T {
return arr[0]
}
foo([1,2,3]) // T代表number
foo(['1']) // T代表string
function foo(arr1:T[],arr2:T[]):T[] {
return arr1.concat(arr2)
}
foo<number|string>([1,2,3],['1','2'])
再看看稍微复杂一点的写法
function myMap (arr:T[],f:(arg:T)=>U):U[]{
return arr.map(f)
}
myMap<string,number>(['1','2','3'],(n)=>parseInt(n))
// 泛型和interface一起用
interface Animal{
name:T
age:U
}
const an:Animal<string,number> = {
name:'dog',
age:2
}
const an2:Animal<number,string> = {
name:3,
age: 'cat'
}
小结
注意:我们定义类型,类型名记得大写
interface vs type
interface:对象模型,专门用于定义一个对象类型且定义对象和对象内部属性的接口
上文还介绍了一些泛型的基本用法,后续将会持续更新。