高端html5网站建设,简单的生产管理系统,中企动力做的网站后台如何登陆,广州专业网站制作公司大家好#xff0c;我是有用就扩散#xff0c;有用就点赞。
TypeScript 基本用法
类型声明 1#xff09;类型声明的写法#xff0c;一律为在标识符后面添加“冒号 类型”。函数参数和返回值#xff0c;也是这样来声明类型。 2#xff09;TypeScript 规定#xff0c;变…大家好我是有用就扩散有用就点赞。
TypeScript 基本用法
类型声明 1类型声明的写法一律为在标识符后面添加“冒号 类型”。函数参数和返回值也是这样来声明类型。 2TypeScript 规定变量只有赋值后才能使用否则就会报错。 类型推断 1类型声明并不是必需的如果没有TypeScript 会自己推断类型。后面如果变量更改为其他类型的值跟推断的类型不一致TypeScript 就会报错。 TypeScript 的编译 1JavaScript 的运行环境浏览器和 Node.js不认识 TypeScript 代码。所以TypeScript 项目要想运行必须先转为 JavaScript 代码这个代码转换的过程就叫做“编译”compile。 2TypeScript 官方没有做运行环境只提供编译器。编译时会将类型声明和类型相关的代码全部删除只留下能运行的 JavaScript 代码并且不会改变 JavaScript 的运行结果。 3因此TypeScript 的类型检查只是编译时的类型检查而不是运行时的类型检查。一旦代码编译为 JavaScript运行时就不再检查类型了。 值与类型 1TypeScript 代码只涉及类型不涉及值。所有跟“值”相关的处理都由 JavaScript 完成。 2这一点务必牢记。TypeScript 项目里面其实存在两种代码一种是底层的“值代码”另一种是上层的“类型代码”。前者使用 JavaScript 语法后者使用 TypeScript 的类型语法。 3它们是可以分离的TypeScript 的编译过程实际上就是把“类型代码”全部拿掉只保留“值代码”。 4编写 TypeScript 项目时不要混淆哪些是值代码哪些是类型代码。 TypeScript Playground 1最简单的 TypeScript 使用方法就是使用官网的在线编译页面叫做 TypeScript Playground。 tsc 编译器 TypeScript 官方提供的编译器叫做 tsc可以将 TypeScript 脚本编译成 JavaScript 脚本。 1安装$ npm install -g typescript 2检查一下是否安装成功$ tsc -v 3帮助信息$ tsc -h 4完整的帮助信息$ tsc --all 5编译脚本 1tsc命令后面加上 TypeScript 脚本文件就可以将其编译成 JavaScript 脚本$ tsc app.ts 2tsc命令也可以一次编译多个 TypeScript 脚本。 3如果想将多个 TypeScript 脚本编译成一个 JavaScript 文件使用--outFile参数。 4编译结果默认都保存在当前目录--outDir参数可以指定保存到其他目录。 5可以使用--target参数指定编译后的 JavaScript 版本。 6编译错误的处理 1如果编译报错tsc命令就会显示报错信息但是这种情况下依然会编译生成 JavaScript 脚本。 2如果希望一旦报错就停止编译不生成编译产物可以使用--noEmitOnError参数 3tsc 还有一个--noEmit参数只检查类型是否正确不生成 JavaScript 文件。 7tsconfig.json 1TypeScript 允许将tsc的编译参数写在配置文件tsconfig.json。只要当前目录有这个文件tsc就会自动读取所以运行时可以不写参数。 ts-node 模块 ts-node 是一个非官方的 npm 模块可以直接运行 TypeScript 代码。 any类型 1any 类型表示没有任何限制该类型的变量可以赋予任意类型的值。 2设为anyTypeScript 实际上会关闭这个变量的类型检查。 3any类型除了关闭类型检查还有一个很大的问题就是它会“污染”其他变量。 4对于开发者没有指定类型、TypeScript 必须自己推断类型的那些变量如果无法推断出类型TypeScript 就会认为该变量的类型是any。 unknown类型 1与any含义相同表示类型不确定可能是任意类型但是它的使用有一些限制不像any那样自由可以视为严格版的any。 2unknown类型的变量不能直接赋值给其他类型的变量除了any类型和unknown类型。 3unknown类型的变量a经过typeof运算以后能够确定实际类型是number就能用于加法运算了。这就是“类型缩小”即将一个不确定的类型缩小为更明确的类型。 4目的是只有明确unknown变量的实际类型才允许使用它防止像any那样可以随意乱用“污染”其他变量。 5总之unknown可以看作是更安全的any。一般来说凡是需要设为any类型的地方通常都应该优先考虑设为unknown类型。 never 1该类型为空不包含任何值。 2如果一个变量可能有多种类型即联合类型通常需要使用分支处理每一种类型。这时处理所有可能的类型之后剩余的情况就属于never类型。 3不可能返回值的函数返回值的类型就可以写成never 4never类型的一个重要特点是可以赋值给任意其他类型。 5为什么never类型可以赋值给任意其他类型呢这也跟集合论有关空集是任何集合的子集。 总之TypeScript 有两个“顶层类型”any和unknown但是“底层类型”只有never唯一一个。
数组类型 1所有成员的类型必须相同但是成员数量是不确定的可以是无限数量的成员也可以是零成员。 2数组的类型有两种写法。第一种写法是在数组成员的类型后面加上一对方括号。第二种写法是使用 TypeScript 内置的 Array 接口。另外数组类型还有第三种写法因为很少用到使用interface 泛型接口。 3正是由于成员数量可以动态变化所以 TypeScript 不会对数组边界进行检查越界访问数组并不会报错。 4TypeScript 允许使用方括号读取数组成员的类型。由于数组成员的索引类型都是number所以Array[number]读取表示数组所有数值索引的成员类型 数组的类型推断 1如果数组变量没有声明类型TypeScript 就会推断数组成员的类型。 2如果变量的初始值是空数组那么 TypeScript 会推断数组类型是any[]。后面为这个数组赋值时TypeScript 会自动更新类型推断。如果初始值不是空数组类型推断就不会更新。 只读数组const 断言 1JavaScript 规定const命令声明的数组变量是可以改变成员的。 2TypeScript 允许声明只读数组方法是在数组类型前面加上readonly关键字。TypeScript 将readonly number[]与number[]视为两种不一样的类型后者是前者的子类型。注意readonly关键字不能与数组的泛型写法一起使用。实际上TypeScript 提供了两个专门的泛型用来生成只读数组的类型。泛型ReadonlyArrayT和ReadonlyT[]都可以用来生成只读数组类型。 3只读数组还有一种声明方法就是使用“const 断言”。 多维数组 TypeScript 使用T[][]的形式表示二维数组T是最底层数组成员的类型。 class 类型
属性的类型 1类的属性可以在顶层声明也可以在构造方法内部声明。 2TypeScript 有一个配置项strictPropertyInitialization只要打开默认是打开的就会检查属性是否设置了初值如果没有就报错。 readonly 修饰符 1属性名前面加上 readonly 修饰符就表示该属性是只读的。实例对象不能修改这个属性。 2readonly 属性的初始值可以写在顶层属性也可以写在构造方法里面。 3构造方法修改只读属性的值也是可以的。或者说如果两个地方都设置了只读属性的值以构造方法为准。在其他方法修改只读属性都会报错。 方法的类型 1类的方法就是普通函数类型声明方式与函数一致。 2构造方法不能声明返回值类型否则报错因为它总是返回实例对象。 存取器方法 1存取器accessor是特殊的类方法包括取值器getter和存值器setter两种方法。 2TypeScript 对存取器有以下规则。 1如果某个属性只有get方法没有set方法那么该属性自动成为只读属性。 2TypeScript 5.1 版之前set方法的参数类型必须兼容get方法的返回值类型否则报错。TypeScript 5.1 版做出了改变现在两者可以不兼容。 3get方法与set方法的可访问性必须一致要么都为公开方法要么都为私有方法。 属性索引 1类允许定义属性索引。 2注意由于类的方法是一种特殊属性属性值为函数的属性所以属性索引的类型定义也涵盖了方法。如果一个对象同时定义了属性索引和方法那么前者必须包含后者的类型。 3属性存取器视同属性。 类的 interface 接口 1implements 关键字 1interface 接口或 type 别名可以用对象的形式为 class 指定一组检查条件。然后类使用 implements 关键字表示当前类满足这些外部类型条件的限制。 2注意interface 描述的是类的对外接口也就是实例的公开属性和公开方法不能定义私有的属性和方法。这是因为 TypeScript 设计者认为私有属性是类的内部实现接口作为模板不应该涉及类的内部代码写法。 2实现多个接口 1类可以实现多个接口其实是接受多重限制每个接口之间使用逗号分隔。 3类与接口的合并 1TypeScript 不允许两个同名的类但是如果一个类和一个接口同名那么接口会被合并进类。 Class 类型 1实例类型 1TypeScript 的类本身就是一种类型但是它代表该类的实例类型而不是 class 的自身类型。 2作为类型使用时类名只能表示实例的类型不能表示类的自身类型。 3由于类名作为类型使用实际上代表一个对象因此可以把类看作为对象类型起名。事实上TypeScript 有三种方法可以为对象类型起名type、interface 和 class。 2类的自身类型 1要获得一个类的自身类型一个简便的方法就是使用 typeof 运算符。 2类的自身类型就是一个构造函数可以单独定义一个接口来表示 3结构类型原则 1Class 也遵循“结构类型原则”。一个对象只要满足 Class 的实例结构就跟该 Class 属于同一个类型。 2如果两个类的实例结构相同那么这两个类就是兼容的可以用在对方的使用场合。只要 A 类具有 B 类的结构哪怕还有额外的属性和方法TypeScript 也认为 A 兼容 B 的类型。 类的继承 1可以使用 extends 关键字继承另一个类这里又称“基类”的所有属性和方法。 2子类可以覆盖基类的同名方法。子类的同名方法不能与基类的类型定义相冲突。 3如果基类包括保护成员protected修饰符子类可以将该成员的可访问性设置为公开public修饰符也可以保持保护成员不变但是不能改用私有成员private修饰符 4注意extends关键字后面不一定是类名可以是一个表达式只要它的类型是构造函数就可以了。 可访问性修饰符 1public修饰符表示这是公开成员外部可以自由访问。public修饰符是默认修饰符如果省略不写实际上就带有该修饰符。因此类的属性和方法默认都是外部可访问的。正常情况下除非为了醒目和代码可读性public都是省略不写的。 2private修饰符表示私有成员只能用在当前类的内部类的实例和子类都不能使用该成员。注意子类不能定义父类私有成员的同名成员。如果在类的内部当前类的实例可以获取私有成员。 1严格地说private定义的私有成员并不是真正意义的私有成员。一方面编译成 JavaScript 后private关键字就被剥离了这时外部访问该成员就不会报错。另一方面由于前一个原因TypeScript 对于访问private成员没有严格禁止使用方括号写法[]或者in运算符实例对象就能访问该成员。 2由于private存在这些问题加上它是 ES2022 标准发布前出台的而 ES2022 引入了自己的私有成员写法#propName。因此建议不使用private改用 ES2022 的写法获得真正意义的私有成员。 3构造方法也可以是私有的这就直接防止了使用new命令生成实例对象只能在类的内部创建实例对象。这时一般会有一个静态方法充当工厂函数强制所有实例都通过该方法生成。 3protected修饰符表示该成员是保护成员只能在类的内部使用该成员实例无法使用该成员但是子类内部可以使用。 1子类不仅可以拿到父类的保护成员还可以定义同名成员。 2在类的外部实例对象不能读取保护成员但是在类的内部可以。 4实例属性的简写形式 1构造方法的参数x前面有public修饰符这时 TypeScript 就会自动声明一个公开属性x不必在构造方法里面写任何代码同时还会设置x的值为构造方法的参数值。注意这里的public不能省略。 2除了public修饰符构造方法的参数名只要有private、protected、readonly修饰符都会自动声明对应修饰符的实例属性。 3readonly还可以与其他三个可访问性修饰符一起使用。 顶层属性的处理方法 1写法一是直接声明一个实例属性age并初始化写法二是顶层属性的简写形式直接将构造方法的参数currentYear声明为实例属性。 2先进行顶层属性的初始化再运行构造方法。这在某些情况下会使得同一段代码在 TypeScript 和 JavaScript 下运行结果不一致。 3这种不一致一般发生在两种情况。 1第一种情况是顶层属性的初始化依赖于其他实例属性。 2第二种情况与类的继承有关子类声明的顶层属性在父类完成初始化。 4为了解决这个问题同时保证以前代码的行为一致TypeScript 从3.7版开始引入了编译设置useDefineForClassFields。这个设置设为true则采用 ES2022 标准的处理方法否则采用 TypeScript 早期的处理方法。 5如果希望避免这种不一致让代码在不同设置下的行为都一样那么可以将所有顶层属性的初始化都放到构造方法里面。 6另一种解决方法就是使用declare命令去声明子类顶层属性的类型告诉 TypeScript 这些属性的初始化由父类实现。 静态成员 1静态成员是只能通过类本身使用的成员不能通过实例对象使用。 2static关键字前面可以使用 public、private、protected 修饰符。 3静态私有属性也可以用 ES6 语法的#前缀表示。 4public和protected的静态成员可以被继承。 泛型类 1类也可以写成泛型使用类型参数。 2注意静态成员不能使用泛型的类型参数。 抽象类抽象成员 1TypeScript 允许在类的定义前面加上关键字abstract表示该类不能被实例化只能当作其他类的模板。这种类就叫做“抽象类”abstract class。 2抽象类只能当作基类使用用来在它的基础上定义子类。 3抽象类的子类也可以是抽象类也就是说抽象类可以继承其他抽象类。 4抽象类的内部可以有已经实现好的属性和方法也可以有还未实现的属性和方法。后者就叫做“抽象成员”abstract member即属性名和方法名有abstract关键字表示该方法需要子类实现。如果子类没有实现抽象成员就会报错。 5这里有几个注意点。 1抽象成员只能存在于抽象类不能存在于普通类。 2抽象成员不能有具体实现的代码。也就是说已经实现好的成员前面不能加abstract关键字。 3抽象成员前也不能有private修饰符否则无法在子类中实现该成员。 4一个子类最多只能继承一个抽象类。 总之抽象类的作用是确保各种相关的子类都拥有跟基类相同的接口可以看作是模板。其中的抽象成员都是必须由子类实现的成员非抽象成员则表示基类已经实现的、由所有子类共享的成员。 类this 问题 1类的方法经常用到this关键字它表示该方法当前所在的对象。 2有些场合需要给出this类型但是 JavaScript 函数通常不带有this参数这时 TypeScript 允许函数增加一个名为this的参数放在参数列表的第一位用来描述函数内部的this关键字的类型。 3this参数的类型可以声明为各种对象。 4TypeScript 提供了一个noImplicitThis编译选项。如果打开了这个设置项如果this的值推断为any类型就会报错。 5在类的内部this本身也可以当作类型使用表示当前类的实例对象。注意this类型不允许应用于静态成员。 类型断言 1类型断言并不是真的改变一个值的类型而是提示编译器应该如何处理这个值。 2类型断言有两种语法。两种语法是等价的value表示值Type表示类型。早期只有语法一后来因为 TypeScript 开始支持 React 的 JSX 语法尖括号表示 HTML 元素为了避免两者冲突就引入了语法二。目前推荐使用语法二。 1语法一类型值示例value 2语法二值 as 类型示例value as Type 3类型断言不应滥用因为它改变了 TypeScript 的类型检查很可能埋下错误的隐患。 4类型断言的一大用处是指定 unknown 类型的变量的具体类型。 类型断言的条件 1类型断言要求实际的类型与断言的类型兼容实际类型可以断言为一个更加宽泛的类型父类型也可以断言为一个更加精确的类型子类型但不能断言为一个完全无关的类型。 2如果真的要断言成一个完全无关的类型也是可以做到的。那就是连续进行两次类型断言先断言成 unknown 类型或 any 类型然后再断言为目标类型。 as const 断言 1如果没有声明变量类型let 命令声明的变量会被类型推断为 TypeScript 内置的基本类型之一const 命令声明的变量则被推断为值类型常量。 2const 命令有更强的限定作用可以缩小变量的类型范围。 3TypeScript 提供了一种特殊的类型断言as const用于告诉编译器推断类型时可以将这个值推断为常量即把 let 变量断言为 const 变量从而把内置的基本类型变更为值类型。 4使用了as const断言以后let 变量就不能再改变值了。as const断言只能用于字面量不能用于变量。另外as const也不能用于表达式。 5as const会将字面量的类型断言为不可变类型缩小成 TypeScript 允许的最小类型。 6as const会将数组变成只读元组所以很适合用于函数的 rest 参数。 7Enum 成员也可以使用as const断言。如果使用as const断言了被Enum某个成员赋值的变量变量的类型就被推断为 Enum 的某个成员。 非空断言 1TypeScript 提供了非空断言保证这些变量不会为空写法是在变量名后面加上感叹号!。 2非空断言会造成安全隐患只有在确定一个表达式的值不为空时才能使用。比较保险的做法还是手动检查一下是否为空。 3非空断言还可以用于赋值断言。TypeScript 有一个编译设置要求类的属性必须初始化即有初始值如果不对属性赋值就会报错。可以使用非空断言表示这个属性肯定会有值。 4另外非空断言只有在打开编译选项strictNullChecks时才有意义。如果不打开这个选项编译器就不会检查某个变量是否可能为undefined或null。 断言函数 1断言函数是一种特殊函数用于保证函数参数符合某种类型。如果函数参数达不到要求就会抛出错误中断程序执行如果达到要求就不进行任何操作让代码按照正常流程运行。 2为了更清晰地表达断言函数TypeScript 3.7 引入了新的类型写法。asserts value is type其中asserts和is都是关键词value是函数的参数名type是函数参数的预期类型。 3如果要断言参数非空可以使用工具类型NonNullableT。 4注意断言函数与类型保护函数type guard是两种不同的函数。它们的区别是断言函数不返回值而类型保护函数总是返回一个布尔值。 5如果要断言某个参数保证为真即不等于false、undefined和nullTypeScript 提供了断言函数的一种简写形式。asserts x省略了谓语和宾语表示参数x保证为真true。 interface 接口 1interface 是对象的模板可以看作是一种类型约定中文译为“接口”。使用了某个模板的对象就拥有了指定的类型结构。 2interface 可以表示对象的各种语法它的成员有5种形式。 1对象属性 2对象的属性索引属性索引共有string、number和symbol三种类型。一个接口中最多只能定义一个数值索引。 3对象的方法对象的方法共有三种写法。 4函数可以用来声明独立的函数。 5构造函数可以使用new关键字表示构造函数。 interface 的继承 1interface 可以使用extends关键字继承其他 interface。interface 允许多重继承。多重接口继承实际上相当于多个父接口的合并。如果子接口与父接口存在同名属性那么子接口的属性会覆盖父接口的属性。如果多个父接口存在同名属性那么这些同名属性不能有类型冲突否则会报错。 2interface 可以继承type命令定义的对象类型。注意如果type命令定义的类型不是对象interface 就无法继承。 3interface 还可以继承 class即继承该类的所有成员。 接口合并 1多个同名接口会合并成一个接口。这样的设计主要是为了兼容 JavaScript 的行为。 2同名接口合并时如果同名方法有不同的类型声明那么会发生函数重载。而且后面的定义比前面的定义具有更高的优先级。 3同名方法之中如果有一个参数是字面量类型字面量类型有更高的优先级。 4如果两个 interface 组成的联合类型存在同名属性那么该属性的类型也是联合类型。 interface 与 type 的异同 1interface命令与type命令作用类似都可以表示对象类型。 2interface 与 type 的区别有下面几点。 1type能够表示非对象类型而interface只能表示对象类型包括数组、函数等。 2interface可以继承其他类型type不支持继承。 3同名interface会自动合并同名type则会报错。 4interface不能包含属性映射mappingtype可以。 5this关键字只能用于interface。 6type 可以扩展原始数据类型interface 不行。 7interface无法表达某些复杂类型比如交叉类型和联合类型但是type可以。 3继承的主要作用是添加属性type定义的对象类型如果想要添加属性只能使用运算符重新定义一个类型。 4继承时type 和 interface 是可以换用的。interface 可以继承 type。type 也可以继承 interface。 欢迎各位大哥投稿PR。