TypeScript入门(上)|青训营笔记

98 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天

这篇文章重点讲述了TypeScript 的发展与基本语法。

一、为什么什么是TypeScript

想要了解一个事物,我们首先可以从它的发展历史来看。接下来我们看一下TypeScript的发展历史。

TypeScript发展历史

  • 2012-10:微软发布了TypeScript 第一个版本(0.8)
  • 2014-10: Angular 发布了基于TypeScript的2.0版本
  • 2015-04:微软发布了Visual Studio Code
  • 2016-05: @types/react 发布,TypeScript 可开发React
  • 2020-09: Vue发布了3.0版本,官方支持TypeScript
  • 2021-11: v4. 5版本发布

知道了它的发展,接下来我们看一下为什么我们要选择TypeScript。

为什么什么是TypeScript

首先我们对比一下JavaScript和TypeScript。

JavaScript和TypeScript相同之处是它们都是弱类型语言。但是不同之处在于JavaScript是动态类型语言,TypeScript是静态类型语言。

那么什么是动态类型语言?什么是静态类型语言?什么是弱类型语言?

  • 动态语言(弱类型语言) 是运行时才确定数据类型的语言,变量在使用之前无需申明类型。比如JavaScript、Python。
  • 静态语言(强类型语言) 是编译时变量的数据类型就可以确定的语言,大多数静态语言要求在使用变量之前必须声明数据类型。比如Java、C、C++、C#。
  • 弱类型语言是数据类型可以被忽略的语言,一个变量可以赋不同数据类型的值。一个变量的类型是由其上下文决定的,效率更高。

下面介绍一下TypeScript的特性:

静态类型

  • 可读性增强:基于语法解析TSDoc, ide增强
  • 可维护性增强:在编译阶段暴露大部分错误

好处:在多人合作的大型项目中,可以获得更好的稳定性和开发效率

JS的超集

  • 包含于兼容所有Js特性,支持共存
  • 支持渐进式引入与升级

编译器推荐

下面是一些编辑器的推荐:

第一个是VSCode

image.png

另外一个是TypeScript官网的一个在线编译器:

image.png

二、TypeScript基本语法

基础数据类型

/*字符串*/
const q: string = 'string';
/*数字*/
const w: number = 1;
/*布尔值*/
const e: boolean = true;
/* null */
const r: null = null;
/* undefined*/
const t: undefined = ndefined;

基础数据类型可以直接翻译,是TypeScript内置的类型。

对象类型

const bytedancer: IBytedancer = {
    jobId: 9303245,
    name: 'Lin ',
    sex: 'man',
    age: 28,
    hobby: 'swimming',
}
interface IBytedancer {
    /*只读属性:约束属性不可在对象初始化外赋值*/
    readonly jobId: number;
    name: string;
    sex: 'man' | 'woman' | 'other';
    age: number;
    /*可选属性:定义该属性可以不存在*/
    hobby? : string;
    /*任意属性:约束所有对象属性都必须是该属性的子类型*/
    [key: string] : any;
}
/*报错:无法分配到“jobId",因为它是只读属性*/
bytedancer.jobId = 12345;
/*成功:任意属性标注下可以添加任意属性*/
bytedancer.plateform = 'data';
/*报错:缺少属性“name" , hobby可缺省*/
const bytedancer2: IBytedancer = {
    jobId: 89757,
    sex: 'woman ',
    age: 18,
}

对象类型大部分情况下都是自定义的。

函数类型

下面介绍的是一个相加的函数。

function add(x: number, y: number): number {
    return x + y;
}
const mult: (x: number, y: number) => number = (x, y) => × * y;

接下来介绍的是一个相乘的函数。

interface IMult {
    (x: number, y: number): number;
}
const mult: IMult = (x,y) => x * y;

函数重载

大多数函数接受一组固定的参数,但有些函数可以接受可变数量的参数,不同类型的参数,甚至可以根据你调用函数的方式返回不同的类型。为了注释这样的函数,TypeScript 提供了函数重载功能。

/*对getDate函数进行重载, timestamp为可缺省参数*/
function getDate(type: 'string ' , timestamp?: string ): string;interface IGetDate {
    (type: 'string ', timestamp?: string): string;
    (type: 'date' , timestamp?: string): Date;
    (type: 'string' | 'date ', timestamp?: string): Date | string;
}
/*不能将类型"(type: any, timestamp: any) => string | Date"分配给类型IGetDate”。
不能将类型“string | Date"分配给类型“string"。
不能将类型"Date"分配给类型“string”。ts (2322)*/
const getDate2: IGetDate = (type,timestamp)=> {
    const date = new Date(timestamp);
    return type a= 'string' ? date.toLocaleString() : date;
}

数组类型

TypeScript 中数组指的是有序的元素序列,它是静态的,一旦初始化就无法调整大小。

/*「类型+方括号」表示*/
type IArr1 = number[];
/*泛型表示*/
type IArr2 = Array<string | number | Record<string,number>>;
/*元组表示*/
type IArr3 = [number, number, string,string] ;
/*接口表示*/
interface IArr4 {
    [key: number] : any;
}
const arr1: IArr1 = [1, 2, 3, 4, 5, 6];
const arr2: IArr2 = [1, 2, '3', '4', { a: 1 }];
const arr3: IArr3 = [1, 2, '3', '4'];
const arr4: IArr4 = [ 'string', () => null, {}, []];

TypeScript的补充类型

下面是一些TypeScript的补充类型。

/*空类型,表示无赋值*/
type IEmptyFunction = () => void;
/*任意类型,是所有类型的子类型*/
type IAnyType = any;
/*枚举类型:支持枚举值到枚举名的正、反向映射*/
enum EnumExample {
    add = '+',
    mult = '*',
}
EnumExample [ 'add ' ] === '+';
EnumExample[ '+'] === 'add ' ;
enum ECorlor { Mon,Tue,wed,ThuFri,Sat,Sun };
ECorlor [ 'Mon ' ] === 0;
ECorlor[0] === 'Mon ';

TypeScript泛型

在TypeScript中,泛型是一创建可复用代码组件的工具。这种组件不只能被一种类型使用,而是能被多种类型复用。

/*泛型*/
type INumArr = Array<number>;
/*不预先指定具体的类型,而在使用的时候再指定类型的一种特性*/
type IGetRepeatArrR = <T>(target: T) => T[];



/*泛型接口&多泛型*/
interface IX<T,U>{
    key: T;
    val: U;
}
/*泛型类*/
class IMan<T>{
    instance: T;
}
/*泛型别名*/
type ITypeArr<T>= Array<T>;

/*泛型约束:限制泛型必须符合字符串*/
type IGetRepeatStringArr = <T extends string>(target: T) => T[];
const getStrArr: IGetRepeatStringArr = target => new Array(100).fill(target);
/*报错:类型"number"的参数不能赋给类型"string"的参数*/
getStrArr(123);


/*泛型参数默认类型*/
type IGetRepeatArr<T = number> = (target: T)=> T[];
const getRepeatArr: IGetRepeatArr = target => new Array(100).fill(target);
/*报错:类型"string"的参数不能赋给类型"number"的参数*/
getRepeatArr( '123' );

类型别名 & 类型断言

有时候函数类型或者联合类型字符串过长,使用起来比较麻烦,可以使用type关键字像定义变量一样给他定义别名。而在联合类型中我们只能使用二者共有的属性或者方法,如果访问非公有属性,编辑器会报错,此时我们就可以预判类型,使用类型断言自己断言这个变量的类型。

/*通过type关键字定义了IObjArr的别名类型*/type 10bjArr = Array<{
    key: string;
    [objKey: string] : any;
}>
function keyBy<T extends IObjArr>(objArr: Array<T>){
    /*未指定类型时,result类型为*/
    const result = objArr.reduce((res, val, key) => {
        res [key] = val;
        return res;
    }, {});
    /*通过as关键字,断言result类型为正确类型*/
    return result as Record<string,T>;
}

字符串/数字 字面量

下面介绍一些字符串和字面量。

/*允许指定字符串/数字必须的固定值*/

/*IDomTag必须为html、body、div、span中的其一*/
type IDomTag = 'html' | 'body' | 'div' | 'span ';
/* IOddNumber必须为1、3、5、7、9中的其一*/
type IOddNumber = 1 | 3 | 5 | 7 |9;

三、总结

通过今天对TypeScript的一个基本学习,我了解到它和JavaScript的一些区别。知道了它的一些优点比如静态类型化,它可以让我们写的代码质量更好、更清晰。除此之外还学习了一些TypeScript,它语法规则JavaScript十分相似,但是也存在一些区别。