面试题
1.类型推论 & 可赋值性
a.什么是类型推论?
若没给定变量指定类型,ts会给标定一个类型,ts根据上下文
b.以下代码ts推论出的类型是什么?
let a = 1024; // number
let b= '1024'; // string
const c = 'apple'; // apple
let d = [true, false, true]; // boolean[]
let e = {name: 'apple'} // object
let f = null; // any
c为什么是apple
c使用const定义的不会被重新复制,是字面量类型,是一个常量,是缩窄,不是拓宽
f为什么是null
ts在做推导时进行类型拓宽,会拓宽到any,拓宽到包容的类型中
可赋值性:数组、布尔、数字、对象、函数、类、字符串、字面量类型,满足以下任一条件时,A类型可以赋值给B类型
(1)A是B的子类型
(2)A是any 类型
规则2是规则1的例外
2.类型断言 指定值类型,缩小范围 断言就是让ts别管了,类型转换是变量类型实际改变
function formatInput(input:string):string{
return input.slice(0,10)
}
function getUserInput():string | number {
return 'test'
}
let input = getUserInput();
formatInput(input as string);
formatInput(<string>input);
3.type和interface的异同
interface侧重于描述数据结构,type(类型别名)侧重于描述类型
type age = number;
type dataType = number | string;
type Method = 'GET' | 'POST' | 'PUT' | 'DELETE';
type User = {
name: string
age:number
}
interface User1 extends User {
age:number
}
const user1:User1 = {
name:'John',
age:12
}
--相同点:
a.都可以描述一个对象或者函数
//interface
interface User {
name:string;
age:number;
}
interface SetUser {
(name:string,age:number):void;
}
//type
type User = {
name:string;
age:number;
}
type SetUser = (name:string,age:number):void
b.interface和type都可以扩展,interface可以extends type,type也可以extends interface.效果差不多,语法不同
// interface extends interface
interface Name {
name:string;
}
interface User extends Name {
age:number;
}
//type extends type
type Name = {
name:string;
}
type User = Nmae & {age:number}
//interface extends type
type Name = {
name:string;
}
interface User extends Name{
age:number
}
//type extends interface
interface Name {
name:string;
}
type User = Name & {age:number};
--不同点
a.类型别名可以用于其他类型(联合类型、元祖类型、基本类型(原始值)),interface不支持 type强调类型,interface强调结构
type PartialPointX = {x:number};
type PartialPointY = {y:number};
//union(联合)
type PartialPoint = PartialPointX | PartialPointY;
//tuple(元组)
type Data = [PartialPointX,PartialPointY];
//primitive(原始值)
type Name = Number;
//typeof的返回值
let div = document.creatElement('div');
type B = typeof div;
b.interface可以多次定义,并被视为合并所有声明成员,type不支持
interface Point {
x:number;
}
interface Point {
y:number;
}
const point:Point = {x:1,y:2};
interface USer {
name:string;
age:number;
}
interface User {
sex:string;
}
//User接口为:
{
name:string;
age:number;
sex:string;
}
c.type能使用in关键字生成映射类型,但interface不行
type Keys = 'firstname' | 'surname';
type DudeType = {
[key in Keys]: string;
};
const test: DudeType = {
firstname:'Pawel',
surname:'Grzybek',
};
提问:
//1
type Options = {
baseURL: string
cacheSize?: number
env?: 'prod' | 'dev'
}
//2
class API {
constructor(options:Options){}
}
//3
new API({
baseURL:'http://myapi.site.com',
env:'prod'
})
//4
new API({
baseURL:'http://myapi.site.com',
badEnv:'prod'
})
//5
new API({
baseURL:'http://myapi.site.com',
badEnv:'prod'
} as Options)
//6
let badOptions = {
baseURL:'http://myapi.site.com',
badEnv: 'prod'
}
new API(badOptions)
//7
let options:Options = {
baseURL:'http://myapi.site.com',
badEnv: 'prod'
}
new API(badOptions)
4.装饰器问题
--装饰器分类及其装饰器参数:
a.类装饰器:类的构造函数
b.方法装饰器:对于静态成员来说是类的构造函数,对于实例成员是类的原型对象;成员的名字;成员的属性描述符
c.访问器装饰器:对于静态成员来说是类的构造函数,对于实例成员是类的原型对象;成员的名字;成员的属性描述符
d.方法参数装饰器:对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象;参数的名字;参数在函数参数列表中的索引
e。属性装饰器:对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象;成员的名字
--执行顺序
a.有多个参数装饰器s时:从最后一个参数依次向前执行
b.方法和方法参数中参数装饰器先执行
c.类装饰器总是最后执行
d.方法和属性装饰器,谁在前面谁先执行。因为参数属于方法的一部分,所以参数会一直紧紧挨着方法执行
5.接口类型
属性类接口 函数类接口 可索引接口 类类型接口 扩展接口