TypeScript入门 | 青训营笔记

15 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第4天,今天学习的内容是TypeScript。

Typescript的发展与基本语法

发展历史

1.png

主流的前端开发框架Angular、React、Vue都支持使用Typescript,同时微软推出的VSCode对typescript支持最好,也可以在官方的在线编辑器练习Typescript。

  • TypeScript源于JavaScript,共同之处是二者都是弱类型语言,但JavaScript 是动态类型语言,TypeScript是静态类型语言。

动态类型的语言特点就是运行的时候才进行类型的检验,而静态语言在写代码的时候就进行类型检验。

弱类型语言的特点是会进行隐式的类型转换,比如字符串的1与整型的1可以相加,强类型语言中类别区分很明确,字符串的1与整型的1不允许相加运算

Typescript的特性

静态类型

  • 可读性增强:基于语法解析TSDoc,使ide的能力有所增强
  • 可维护性增强:在编译阶段暴露大部分错误,使合作项目更加便捷高效。让多人合作的大型项目获得更好的稳定性和开发效率

JS的超集

  • ·包含于兼容所有JS特性,支持共存,让原生程序员更快接受
  • 支持渐进式引入与升级

基本语法

基础数据类型定义

Javascript常见的数据类型定义,TypeScript有自动类型推断,故以下代码可以在TS环境中运行。

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

转换为TS代码

const q: string = 'string';/*字符串*/
const w: number = 1;/*数字*/
const e: boolean = true;/*布尔值*/
const r: null = null;/* null */
const t: undefined = undefined;/* undefined */
const 变量名:类型 = xx;
let 变量名:类型 = xx;

对象数据类型

interface IBytedancer{
    /*只读属性:约束属性不可在对象初始化外赋值*/
    readonly jobId: number;
    name: string;
    sex: 'man'| 'woman' | 'other';
    age: number;
    /*可选属性:定义该属性可以不存在*/
    hobby?: string;
    /*任意属性:约束所有对象属性都必须是该属性的子类型*/
    [key: string] : any;
}

[key: string]是将未知属性的类型定义为any,比如后添加的属性。

any是TS特有的类型,能够为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。

这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用any类型来标记这些变量。

const bytedancer: IBytedancer = {
    jobId: 9303245,
    name: 'Lin',
    sex: 'man',
    age: 28,
    hobby: 'swimming',
}

/*报错:无法分配到"jobId",因为它是只读属性*/
bytedancer.jobId = 12345;
/*成功:任意属性标注下可以添加任意属性*/
bytedancer.plateform = 'data';
/*报错:缺少属性"“name" , hobby可缺省*/
const bytedancer2: IBytedancer = {
    jobId: 89757,
    sex: 'woman',
    age: 18,
}

函数类型

原本JS中定义加和乘的代码

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

改写成TS有两种方式,在所有需要声明类型的地方加上即参数和返回值。

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

第二种是定义interface,会更加清晰,比在匿名函数中每处加类型更易理解。

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

数组类型

/*「类型+方括号」表示*/
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, {}, []];

type作用就是给类型起一个新名字,可以理解成和接口一样,用来描述对象或函数的类型。

我们常用第一种和第二种定义数组,第四种数组是任意类型的数组。