1、类型声明
let 变量: 类型;
let 变量: 类型 = 值;
function fn(参数: 类型, 参数: 类型): 类型{
...
}
let fn1:function fn(参数: 类型, 参数: 类型)=>返回值类型
ts
拥有自动判题机制
2、类型
类型 | 例子 | 描述 |
---|---|---|
number | 1, -33, 2.5 | 任意数字 |
string | ‘hi’, “hi”, hi | 任意字符串 |
boolean | true、false | 布尔值true或false |
字面量 | 其本身 | 限制变量的值就是该字面量的值 |
any | * | 任意类型 |
unknown | * | 类型安全的any |
void | 空值(undefined) | 没有值(或undefined) |
never | 没有值 | 不能是任何值 |
object | {name:‘孙悟空’} | 任意的JS对象 |
array | [1,2,3] | 任意JS数组 |
tuple | [4,5] | 元素,TS新增类型,固定长度数组 |
enum | enum{A, B} | 枚举,TS中新增类型 |
1)ts类型 :用 |
来连接多个类型 --联合类型
let b : "male" | "female"
b = "male"
b = "female"
b = "str" //报错
let c : boolean | string
c = true
c = "str"
c = 1 //报错
2)any:可以赋值给其他任意变量
let d
let e: any
d = "a"
d = 1
e = "a"
e = 1
3):unknown:表示未知类型的值,不能赋值给其他任意变量
let c:string
c = "str"
let s : unknown
s= "1"
s = 1
s= true
c = s //报错
-
类型断言:可以告诉解析器变量的实际类型
let c:string let s : unknown c = s as string //不报错 c = <string>s //不报错
4)void:表示空,如果是函数则表示没有返回值
function sum(a: number, b: number) {
//function sum(a: number, b: number): void
}
function sum(a: number, b: number) {
//function sum(a: number, b: number): number
return a + b
}
- 可以返回
null
或undefined
5)never:表示永远不会返回结果
function fn(): never {
throw new Error("报错了!")
}
function fn(): never { //报错:返回“从不”的函数不能具有可访问的终结点
}
6)object:表示一个 js 对象
let b: { name: string, age: number }
b = {} //报错
b = { name: "hhh" } //报错 -> 如果想不报错,就要在b的属性age后面加上? let b: { name: string, age?: number }
b = { name: "hhh", age: 18 } //不报错
let c: { name: string, [propName: string]: any }
c = { name: "ggg", a: 1, b: true } //不报错
{}
用来指定对象可以包含哪些属性- 语法:{属性名:属性值,属性名:属性值,…}
- 在属性名后面加上
?
表示属性是可选的 [propName: string]: any
:表示任意类型的属性
7)数组
let a: string[]
a = ["a", "b"]
let b: number[]
b = [1, 3]
let c: Array<number>
c = [2, 4]
- 类型[ ]
- Array<类型>
8)元组:固定长度的数组
let h :[string,number]
h = ["hello",1]
9):enum:枚举
enum Color {
Red = 1,
Green = 2,
Blue = 3,
}
let a: { name: string, likeColor: Color }
a = { name: "hh", likeColor: Color.Blue }
10):&表示同时
let j: { name: string } & { age: number }
j = { name: "hh" } //报错
j = { name: "hh", age: 18 } //不报错
11)类型的别名
type myTypes = 1 | 2 | 3
let k : myTypes
k = 2 //不报错
k = 4 //报错:不能将类型“4”分配给类型“myTypes
3、ts编译选项
编译配置文件:tsconfig.json
{
"compilerOptions": { // 编译选项
"target": "esnext", // 设置ts代码编译的目标版本
// ES3(默认)、ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext
"module": "esnext", //设置编译后代码使用的模块化系统
// CommonJS、UMD、AMD、System、ES2020、ESNext、None
"outDir": "dist", // 编译后文件的所在目录
"strict": true, // 用所有的严格检查,默认值为true
"jsx": "preserve",
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"useDefineForClassFields": true,
"sourceMap": true, // 是否生成sourceMap,默认值:false
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [ // 指定代码运行时所包含的库(宿主环境)
// ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext、DOM、WebWorker、ScriptHost ......
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
// 希望被编译的文件 默认["**/*"]
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
// 希望不被编译的文件 默认["node_modules", "bower_components", "jspm_packages"]
"exclude": [
"node_modules"
]
}
-
严格检查:
strict
- 启用所有的严格检查,默认值为true,设置后相当于开启了所有的严格检查
alwaysStrict
- 总是以严格模式对代码进行编译
noImplicitAny
- 禁止隐式的any类型
noImplicitThis
- 禁止类型不明确的this
strictBindCallApply
- 严格检查bind、call和apply的参数列表
strictFunctionTypes
- 严格检查函数的类型
strictNullChecks
- 严格的空值检查
strictPropertyInitialization
- 严格检查属性是否初始化
-
额外检查
noFallthroughCasesInSwitch
- 检查switch语句包含正确的break
noImplicitReturns
- 检查函数没有隐式的返回值
noUnusedLocals
- 检查未使用的局部变量
noUnusedParameters
- 检查未使用的参数
-
高级
allowUnreachableCode
- 检查不可达代码
- 可选值:
- true,忽略不可达代码
- false,不可达代码将引起错误
noEmitOnError
- 有错误的情况下不进行编译
- 默认值:false
4、webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
optimization:{
minimize: false // 关闭代码压缩,可选
},
entry: "./src/index.ts",
devtool: "inline-source-map",
devServer: {
contentBase: './dist'
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
environment: {
arrowFunction: false // 关闭webpack的箭头函数,可选
}
},
resolve: {
extensions: [".ts", ".js"]
},
module: {
rules: [
{
test: /\.ts$/,
use: {
loader: "ts-loader"
},
exclude: /node_modules/
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title:'TS测试'
}),
]
}
引入Babel
对代码进行转换,以使其可以兼容到更多的浏览器
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
optimization:{
minimize: false // 关闭代码压缩,可选
},
entry: "./src/index.ts",
devtool: "inline-source-map",
devServer: {
contentBase: './dist'
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
environment: {
arrowFunction: false // 关闭webpack的箭头函数,可选
}
},
resolve: {
extensions: [".ts", ".js"]
},
module: {
rules: [
{
test: /\.ts$/,
use: [
{
loader: "babel-loader",
options:{
presets: [
[
"@babel/preset-env",
{
"targets":{
"chrome": "58",
"ie": "11"
},
"corejs":"3",
"useBuiltIns": "usage"
}
]
]
}
},
{
loader: "ts-loader",
}
],
exclude: /node_modules/
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title:'TS测试'
}),
]
}
如此一来,使用ts编译后的文件将会再次被babel处理;
使得代码可以在大部分浏览器中直接使用;
同时可以在配置选项的targets中指定要兼容的浏览器版本;
5、类
class 类名{
属性名= 属性值;
属性名= 属性值;
属性名= 属性值;
...
// 方法
方法名(){
...
}
}
// 1. 使用方式
// 1) new
const xx = new 类名
xx.属性名
// 2)直接使用(这个需要在属性名前面加上 static,变成静态属性)
类目.属性名
// 2. 只读属性 readonly -> 添加到属性名前面(在 static 后面),只允许读取,不允许修改
6、构造函数
class Dog {
name: string
age: number
constructor(name:string , age:number){
this.name = name
this.age = age
}
}
const dog1 = new Dog("小黑", 20)
const dog2 = new Dog("小白", 20)
7、extends:继承
class 父类{
属性名: 类型;
属性名: 类型;
...
方法名(){
}
}
class 子类 extends 父类{
// 如果方法名和父类的相同,就相当于重写了父类方法,但父类不受影响
方法名(){
}
}
8、super
class 父类{
父类属性名: 类型;
父类属性名: 类型;
...
constructor(父类属性名:类型 , 父类属性名:类型){
this.父类属性名 = 父类属性名
this.父类属性名 = 父类属性名
}
}
class 子类 extends 父类{
子类属性名: 类型;
...
// 因为方法名一致,所以会重写父类方法,所以要先调用父类方法
constructor(父类属性名:类型 , 子类属性名:number){
super(父类属性名:类型 , 父类属性名:类型)
this.子类属性名 = 子类属性名
}
}
9、abstract 抽象:出生就是为了当爸爸的
abstract class 父类{
父类属性名: 类型;
父类属性名: 类型;
...
constructor(父类属性名:类型 , 父类属性名:类型){
this.父类属性名 = 父类属性名
this.父类属性名 = 父类属性名
}
// 子类必须重写父类的方法
abstract 方法名():[返回参数];
}
class 子类 extends 父类{
// 重写父类方法
方法名():[返回参数]{
...
}
}
10、interface:接口(implements)
interface myInter {
name: string
fn(): void
}
class myClass implements myInter{
name: string
constructor(name:string){
this.name = name
}
fn(): void {
console.log("实现了接口方法");
}
}
11、封装
public:
class Person{
public name: string; // 写或什么都不写都是public
public age: number;
constructor(name: string, age: number){
this.name = name; // 可以在类中修改
this.age = age;
}
sayHello(){
console.log(`大家好,我是${this.name}`);
}
}
class Employee extends Person{
constructor(name: string, age: number){
super(name, age);
this.name = name; //子类中可以修改
}
}
const p = new Person('孙悟空', 18);
p.name = '猪八戒';// 可以通过对象修改
protected:
class Person{
protected name: string;
protected age: number;
constructor(name: string, age: number){
this.name = name; // 可以修改
this.age = age;
}
sayHello(){
console.log(`大家好,我是${this.name}`);
}
}
class Employee extends Person{
constructor(name: string, age: number){
super(name, age);
this.name = name; //子类中可以修改
}
}
const p = new Person('孙悟空', 18);
p.name = '猪八戒';// 不能修改
private:
class Person{
private name: string;
private age: number;
constructor(name: string, age: number){
this.name = name; // 可以修改
this.age = age;
}
sayHello(){
console.log(`大家好,我是${this.name}`);
}
}
class Employee extends Person{
constructor(name: string, age: number){
super(name, age);
this.name = name; //子类中不能修改
}
}
const p = new Person('孙悟空', 18);
p.name = '猪八戒';// 不能修改
属性存取器
对于一些不希望被任意修改的属性,可以将其设置为private
直接将其设置为private将导致无法再通过对象修改其中的属性
我们可以在类中定义一组读取、设置属性的方法,这种对属性读取或设置的属性被称为属性的存取器
读取属性的方法叫做setter方法,设置属性的方法叫做getter方法
示例:
class Person{
private _name: string;
constructor(name: string){
this._name = name;
}
get name(){
return this._name;
}
set name(name: string){
this._name = name;
}
}
const p1 = new Person('孙悟空');
// 实际通过调用getter方法读取name属性
console.log(p1.name);
// 实际通过调用setter方法修改name属性
p1.name = '猪八戒';
简写属性
class Dog{
constructor(name:string,age:number){}
}
const dog = new Dog("小黑",2)
12、泛型
// 泛型函数
function test<T>(arg: T): T{
return arg;
}
// 泛型类
class MyClass<T>{
prop: T;
constructor(prop: T){
this.prop = prop;
}
}
// 泛型继承
interface MyInter{
length: number;
}
function test<T extends MyInter>(arg: T): number{
return arg.length;
}