1.使用TS的好处是什么?
1.1:TypeScript 是 JavaScript的超集,给js添加了可选的静态类型和基于类的面向对象编程,拓展了js的语法,ts的功能比js只多不少;
1.2:ts 面向对象的编程语言,包含类和接口的概念;
1.3:在开发阶段就能给出编译错误,而js错误则需要在运行时才能暴露;
1.4:是一种强类型语言,你可以明确的知道各种数据类型,代码可读性强,几乎每个人都能很快理解;
1.5:ts中有很多很多方便的特性,可选链; // optional chain
const obj = response;
// js
if(obj && obj.aa && obj.aa.bb){
const val = obj.aa.bb;
}
// ts
if(obj?.aa?.bb){
const val = obj.aa.bb;
}
2.type 和 interface的区别?
用interface来描述数据结构,用type来描述类型。 2.1:都支持描述一个对象或函数;
interface User{
name: string;
age: number;
}
type User = {
name: string;
age: number;
}
2.2:都允许扩展extends; interface和type都允许extends,interface是可以extends type,type也可以extends interface。
type Name = {
name:string;
}
interface User extends Name {
}
2.3:只有type可以做的事情; type可以声明基本数据类型,联合类型,元组类型。
type Name = string;
interface Dog {
wong();
}
interface Cat {
miao();
}
type Pet = Dog | Cat; // 联合类型
type PetList = [Dog,Cat]; // 元组类型
3.如何基于一个已有类型,扩展出一个大部分内容相似,但是部分区别的类型?
Pick Omit
interface Test {
name: string;
sex: string;
age: number;
}
type Sex = Pick<Test, 'sex'>; // string
const a: Sex = { sex:1 };
type WithoutSex = Omit<Test, 'sex'>;
const b: WithoutSex = { name:'aa', age:18 }
4.什么是泛型?泛型的具体使用?
泛型是指在定义函数、接口或者类的时候,不预先执行具体类型,使用的时候再去指定类型的一种特性。
interface Test<T = any> {
userId: T;
}
type TestA = Test<string>; // { userId:string }
5:TypeScript 中 const 和 readonly 的区别?枚举和常量枚举的区别
const 和 readonly: const可以防止变量的值被修改,readonly可以防止变量的属性被修改。
枚举和常量枚举: 常量枚举只能使用常量枚举表达式,并且不同于常规的枚举,它们在编译阶段会被删除。 常量枚举成员在使用的地方会被内联进来。 之所以可以这么做是因为,常量枚举不允许包含计算成员。
6:TypeScript 中 any、never、unknown、null & undefined 和 void 有什么区别
any: 动态的变量类型(失去了类型检查的作用)。
never: 永不存在的值的类型。例如:never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。
unknown: 任何类型的值都可以赋给 unknown 类型,但是 unknown 类型的值只能赋给 unknown 本身和 any 类型。
null & undefined: 默认情况下 null 和 undefined 是所有类型的子类型。 就是说你可以把 null 和 undefined 赋值给 number 类型的变量。当你指定了 --strictNullChecks 标记,null 和 undefined 只能赋值给 void 和它们各自。
void: 没有任何类型。例如:一个函数如果没有返回值,那么返回值可以定义为void。
7:TypeScript 中 interface 可以给 Function / Array / Class(Indexable)做声明吗
// 函数声明
interface Say {
(name: string): viod;
}
let say: Say = (name: string):viod => {}
// Array 声明
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
// Class 声明
interface PersonalIntl {
name: string sayHi (name: string): string
}
8:TypeScript 中的 this 和 JavaScript 中的 this 有什么差异?
- TypeScript:noImplicitThis: true 的情况下,必须去声明 this 的类型,才能在函数或者对象中使用this。
- Typescript 中箭头函数的 this 和 ES6 中箭头函数中的 this 是一致的。
9:TypeScript 中 ?.、??、!、!.、_、** 等符号的含义?
?. 可选链 遇到 null 和 undefined 可以立即停止表达式的运行。
?? 空值合并运算符 当左侧操作数为 null 或 undefined 时,其返回右侧的操作数,否则返回左侧的操作数。
! 非空断言运算符 x! 将从 x 值域中排除 null 和 undefined
!. 在变量名后添加,可以断言排除undefined和null类型
_ 数字分割符 分隔符不会改变数值字面量的值,使人更容易读懂数字 .e.g 1_101_324。
** 求幂
10:简单聊聊你对 TypeScript 类型兼容性的理解?
ts 类型兼容: 当一个类型 Y 可以赋值给另一个类型 X 时, 我们就可以说类型 X 兼容类型 Y。也就是说两者在结构上是一致的,而不一定非得通过 extends 的方式继承而来
接口的兼容性:X = Y 只要目标类型 X 中声明的属性变量在源类型 Y 中都存在就是兼容的( Y 中的类型可以比 X 中的多,但是不能少)
函数的兼容性:X = Y Y 的每个参数必须能在 X 里找到对应类型的参数,参数的名字相同与否无所谓,只看它们的类型
11:协变、逆变、双变和抗变的理解?
协变:X = Y Y 类型可以赋值给 X 类型的情况就叫做协变,也可以说是 X 类型兼容 Y 类型
interface X { name: string; age: number; }
interface Y { name: string; age: number; hobbies: string[] }
let x: X = { name: 'xiaoming', age: 16 }
let y: Y = { name: 'xiaohong', age: 18, hobbies: ['eat'] }
x = y
逆变:printY = printX 函数X 类型可以赋值给函数Y 类型,因为函数Y 在调用的时候参数是按照Y类型进行约束的,但是用到的是函数X的X的属性和方法,ts检查结果是类型安全的。这种特性就叫做逆变,函数的参数有逆变的性质。
let printY: (y: Y) => void
printY = (y) => { console.log(y.hobbies) }
let printX: (x: X) => void
printX = (x) => { console.log(x.name) }
printY = printX
双变(双向协变):X = Y;Y = X父类型可以赋值给子类型,子类型可以赋值给父类型,既逆变又协变,叫做“双向协变”(ts2.x 之前支持这种赋值,之后 ts 加了一个编译选项 strictFunctionTypes,设置为 true 就只支持函数参数的逆变,设置为 false 则支持双向协变)
抗变(不变):非父子类型之间不会发生型变,只要类型不一样就会报错。
12:TypeScript 中同名的 interface会合并 或者同名的 interface 和 class 可以合并吗?
同名的interface会合并,同名的 interface 和 class会聚合
13:declare,declare global是什么?
declare 是用来定义全局变量、全局函数、全局命名空间、js modules、class等。
declare global 为全局对象 window 增加新的属性。
declare global {
interface Window {
csrf: string;
}
}
14:对 TypeScript 类中成员的 public、private、protected、readonly 修饰符的理解?
public: 成员都默认为public,被此限定符修饰的成员是可以被外部访问;
private: 被此限定符修饰的成员是只可以被类的内部访问;
protected: 被此限定符修饰的成员是只可以被类的内部以及类的子类访问;
readonly: 关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。
15:简述工具类型 Exclude、Omit、Merge、Intersection、Overwrite的作用。
Exclude<T, U> 从 T 中排除出可分配给 U的元素。
Omit<T, K> 的作用是忽略T中的某些属性。
Merge<O1, O2> 是将两个对象的属性合并。
Compute<A & B> 是将交叉类型合并
Intersection<T, U>的作用是取T的属性,此属性同样也存在与U。
Overwrite<T, U> 是用U的属性覆盖T的相同属性。
实战后续有时间在介绍...