这是我参与「第四届青训营 」笔记创作活动的第1天,因为本次涉及到笔者比较喜欢的知识点,因此写下这篇文章记录一下。
写在前面
JavaScript的动态类型语言, 而Typescript是弱类型语言,比如说在js里面数字可以直接和字符串(相当于执行了toString()函数)相加,ts不行。ts是js的超集,对于静态语言ts,可以大幅增加可读性和可维护性,在编译阶段暴露大部分错误,因此,如今大型的前端项目都转换成ts进行编写。
基础数据类型
/* 字符串 */
const q = 'string'; => const q: string = 'string';
/* number */
const w = 1; => const w: number = 1;
/* boolen */
const h = boolen;
/* null */
const r = null;
/* undefined */
const t = undefined;
类型声明及约束
对象类型
下图演示对对象类型进行类型约束,对于interface对象前的首字母I,是我们约定俗称对象名称的首字母,用于区分普通对象。
const class = IClass = {
id: 1,
language: 'zh',
comment: 'test'
}
interface IClass {
/* 只读属性: 不可以在对象初始化外赋值 */
readonly id: number;
language: 'zh'|'en'|'other';
/* 可选属性 */
comment?: string;
/* 任意书写: 约束所有对象属性都必须是该属性的子类型 */
[key: string]: any;
}
当进行如下的赋值/初始化的时候会有下面结果
/* 报错,"id" 为只读属性 */
class.id = 111;
/* 成功 */
class.test = 'test';
/* 报错,缺少必须属性"id" */
const _class : IClass = {
comment: '1111'
}
函数类型
函数也是js中常用到的,比如下面有一个函数
// javascript
function add(x, y){
return x + y;
}
const mult = (x, y) => x * y;
改写成typescript则为
// typescript
function add(x: number , y: number){
return x + y;
}
const mult = (x: number, y: number) => number = (x, y) => x*y;
即在对应变量名后面添加上数据类型,同时typescript也支持如下的interface定义
interface IMult {
(x: number, y: number): number;
}
const mult: IMult = (x, y) => x*y;
函数重载
我们可以通过函数重栽判断数据类型,从而函数实现多种功能,如使用interface:
interface IGetDate {
(type: 'string', time?: string): string;
(type: 'date', time?: string): Date;
(type: 'string' | 'date', time?: string): string | Date;
}
const getDate : IGetDate = (type, timestramp) => {
const date = new Date(timestramp);
return type==='date' ? date.toString() : date
}
但是这样会报错
Type '(type: any, timestramp: any) => string | Date' is not assignable to type 'IGetDate'.\
Type 'string | Date' is not assignable to type 'string'.
Type 'Date' is not assignable to type 'string'.ts(2322)
因为ts会自动判断返回类型,当interface定义的范围小于实例类型时则会报错。这时候其实可以对实例对象修改,也可以对interface进行修改。
数组类型
// 类型+方块号表示
type IArr1 = number[];
//范型
type IArr2 = Array<string | number | Record<string, number>>;
补充类型和枚举类型
除了前面所提到的特征,ts还提供了丰富的补充类型,如枚举类型,
TypeScript 在 ES 原有类型基础上加入枚举类型,使得在 TypeScript 中也可以给一组数值赋予名字,这样对开发者比较友好,可以理解枚举就是一个字典。枚举类型使用enum来定义:
具体可参考:juejin.cn/post/699831…
enum EnumExample {
add = '+',
mult = '*'
}
与此同时,ts支持范型,类似于c++中的模版template,如
type IGetRepeatArr = <T>(target: T) => T[];
其中范型的作用还有其它种运用实例,本质上还是通过其他方式来做类型约束。
高级类型
联合/交叉类型
- 使用 IA | IB 表示其中的几种类型可选
- 使用 IA & IB 多种类型联合一起,包含全部特征
类型守卫
在写js为了函数复用扩展时,可能会有遇到这样的问题
function foo(props)
{
if(typeof(props) === 'string')
{
//true
}else
{
//false
}
}
那么在TS中同样也会遇到一样的问题,我们可能会这么写
interface IA { a:1, a1: 2}
interface IB { b:1, b1: 2}
function log(arg: IA | IB)
{
if(arg.a){
console.log(arg.a1)
}
else{
console.log(arg.b1)
}
}
但是会报错,因为类型IA|IB不存在公共属性"a",在类型联合时,程序属于安全状态,仅仅能访问联合类型的交集部分。那么可以怎么改呢?
interface IA { a:1, a1: 2}
interface IB { b:1, b1: 2}
function getIsIA(arg: IA|IB): arg is IA{
return !!(arg as IA).a;
}
function log(arg: IA | IB)
{
if(getIsIA(arg)){
console.log(arg.a1)
}
else{
console.log(arg.b1)
}
}
这里使用了is限定生效范围,且返回值是一个类型谓词,这样即可以完成类型保护。
写在后面
还没有写到的部分有比如说ts的工程实践,这个可以使用webpack打包/检查,及通过TSC进行编译,因为这是基础的入门篇,因此暂时记录下这么多笔记。