Оглавление
Быстрый старт
0. Введение в TypeScript
- TypeScript — это расширенная версия JavaScript.
- Он расширяет JS, вводит в JS концепцию типов и добавляет множество новых функций.
- Код TS должен быть скомпилирован в JS компилятором, а затем выполнен парсером JS.
- TS полностью совместим с JS. Другими словами, любой JS-код можно использовать непосредственно как JS.
- По сравнению с JS, TS имеет статические типы, более строгий синтаксис и более мощные функции; TS может выполнять проверку кода до его выполнения, уменьшая вероятность исключений во время выполнения; Код TS можно компилировать Для любой версии кода JS он может эффективно решить проблемы совместимости различных рабочих сред JS; для одной и той же функции объем кода TS больше, чем у JS, но поскольку структура кода TS более понятна, а типы переменных более понятны, в более позднем обслуживании кода TS является намного лучше, чем JS.
1. Создание среды разработки TypeScript.
-
下载Node.js
64 место: https://nodejs.org/dist/v14.15.1/node-v14.15.1-x64.msi
32 место: https://nodejs.org/dist/v14.15.1/node-v14.15.1-x86.msi -
Установите Node.js
-
Установите typescript глобально с помощью npm
npm i -g typescript
-
Создать файл ts
-
Используйте tsc для компиляции ts-файлов
-
Введите командную строку
-
Введите каталог, в котором находится файл ts.
-
Выполнение заказа
-
tsc xxx.ts
2. Основные типы
объявление типа
-
Объявление типа — очень важная особенность TS.
-
Тип переменных (параметров, формальных параметров) в TS можно указать посредством объявления типа.
-
После указания типа при присвоении значения переменной компилятор TS автоматически проверит, соответствует ли значение объявлению типа, и присвоит значение, если оно соответствует, в противном случае будет сообщено об ошибке.
-
Короче говоря, объявление типа устанавливает тип переменной так, чтобы она могла хранить значения только определенного типа.
-
грамматика:
let 变量: 类型; let 变量: 类型 = 值; function fn(参数: 类型, 参数: 类型): 类型{ ... }
Автоматическое определение типа
- TS имеет механизм автоматического определения типа.
- Когда объявление и присвоение переменных выполняются одновременно, компилятор TS автоматически определяет тип переменной.
- Поэтому, если объявление и присвоение переменной выполняются одновременно, вы можете опустить объявление типа.
тип:
тип | пример | описывать |
---|---|---|
число | 1, -33, 2,5 | любой номер |
нить | «Привет»,hi |
любая строка |
логическое значение | правда, ложь | логическое значение true или false |
буквальный | сам | Значение переменной ограничения является значением литерала |
любой | * | любой тип |
неизвестный | * | Типобезопасный любой |
пустота | нулевое значение (не определено) | Нет значения (или неопределенно) |
никогда | неважно | не может быть никакого значения |
объект | {name:'Сунь Укун'} | Любой JS-объект |
множество | [1,2,3] | Произвольный массив JS |
кортеж | [4,5] | Элемент, новый тип TS, массив фиксированной длины |
перечисление | перечисление {А, Б} | Перечисление, новый тип в TS |
-
число
let decimal: number = 6; let hex: number = 0xf00d; let binary: number = 0b1010; let octal: number = 0o744; let big: bigint = 100n;
-
логическое значение
let isDone: boolean = false;
-
нить
let color: string = "blue"; color = 'red'; let fullName: string = `Bob Bobbington`; let age: number = 37; let sentence: string = `Hello, my name is ${ fullName}. I'll be ${ age + 1} years old next month.`;
-
буквальный
Вы также можете использовать литералы для указания типа переменной и использовать литералы для определения диапазона значений переменной.
let color: 'red' | 'blue' | 'black'; let num: 1 | 2 | 3 | 4 | 5;
-
любой
let d: any = 4; d = 'hello'; d = true;
-
неизвестный
let notSure: unknown = 4; notSure = 'hello';
-
пустота
let unusable: void = undefined;
-
никогда
function error(message: string): never { throw new Error(message); }
-
объект (бесполезный)
let obj: object = { };
-
множество
let list: number[] = [1, 2, 3]; let list: Array<number> = [1, 2, 3];
-
кортеж
let x: [string, number]; x = ["hello", 10];
-
перечисление
enum Color { Red, Green, Blue, } let c: Color = Color.Green; enum Color { Red = 1, Green, Blue, } let c: Color = Color.Green; enum Color { Red = 1, Green = 2, Blue = 4, } let c: Color = Color.Green;
-
утверждение типа
В некоторых случаях тип переменной нам очень ясен, но компилятору TS он не ясен. В это время компилятору можно сообщить тип переменной через утверждение типа. Существует две формы утверждения:
-
Первый
let someValue: unknown = "this is a string"; let strLength: number = (someValue as string).length;
-
Второй вид
let someValue: unknown = "this is a string"; let strLength: number = (<string>someValue).length;
-
3. Параметры компиляции
Автоматически компилировать файлы
При компиляции файла после использования директивы -w компилятор TS автоматически отслеживает изменения в файле и перекомпилирует файл при его изменении.
Пример:
tsc xxx.ts -w
Автоматическая компиляция всего проекта
-
Если вы используете инструкцию tsc напрямую, все файлы ts в текущем проекте могут быть автоматически скомпилированы в файлы js.
-
Но чтобы иметь возможность использовать команду tsc напрямую, необходимо сначала создать файл конфигурации ts tsconfig.json в корневом каталоге проекта.
-
tsconfig.json — это файл JSON. После добавления файла конфигурации вам понадобится только команда tsc, чтобы завершить компиляцию всего проекта.
Варианты конфигурации:
- include
- 定义希望被编译文件所在的目录
- 默认值:["\*\*/\*"]
示例:
- ```json
"include":["src/**/*", "tests/**/*"]
```
- 上述示例中,所有src目录和tests目录下的文件都会被编译
exclude
- 定义需要排除在外的目录
- 默认值:["node_modules", "bower_components", "jspm_packages"]
示例:
- ```json
"exclude": ["./src/hello/**/*"]
```
- 上述示例中,src下hello目录下的文件都不会被编译
- extends
- 定义被继承的配置文件
示例:
- ```json
"extends": "./configs/base"
```
- 上述示例中,当前配置文件中会自动包含config目录下base.json中的所有配置信息
- files
- 指定被编译文件的列表,只有需要编译的文件少时才会用到
示例:
- ```json
"files": [
"core.ts",
"sys.ts",
"types.ts",
"scanner.ts",
"parser.ts",
"utilities.ts",
"binder.ts",
"checker.ts",
"tsc.ts"
]
```
- 列表中的文件都会被TS编译器所编译
compilerOptions
- 编译选项是配置文件中非常重要也比较复杂的配置选项
- 在compilerOptions中包含多个子选项,用来完成对编译的配置
项目选项
- target
- 设置ts代码编译的目标版本
- 可选值:
- ES3(默认)、ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext
示例:
- ```json
"compilerOptions": {
"target": "ES6"
}
```
- 如上设置,我们所编写的ts代码将会被编译为ES6版本的js代码
- lib
- 指定代码运行时所包含的库(宿主环境)
- 可选值:
- ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext、DOM、WebWorker、ScriptHost ......
示例:
- ```json
"compilerOptions": {
"target": "ES6",
"lib": ["ES6", "DOM"],
"outDir": "dist",
"outFile": "dist/aa.js"
}
```
- module
- 设置编译后代码使用的模块化系统
- 可选值:
- CommonJS、UMD、AMD、System、ES2020、ESNext、None
示例:
- ```typescript
"compilerOptions": {
"module": "CommonJS"
}
```
- outDir
- 编译后文件的所在目录
- 默认情况下,编译后的js文件会和ts文件位于相同的目录,设置outDir后可以改变编译后文件的位置
示例:
- ```json
"compilerOptions": {
"outDir": "dist"
}
```
- 设置后编译后的js文件将会生成到dist目录
- outFile
- 将所有的文件编译为一个js文件
- 默认会将所有的编写在全局作用域中的代码合并为一个js文件,如果module制定了None、System或AMD则会将模块一起合并到文件之中
示例:
- ```json
"compilerOptions": {
"outFile": "dist/app.js"
}
```
- rootDir
- 指定代码的根目录,默认情况下编译后文件的目录结构会以最长的公共目录为根目录,通过rootDir可以手动指定根目录
示例:
- ```json
"compilerOptions": {
"rootDir": "./src"
}
```
- allowJs
- 是否对js文件编译
- checkJs
- 是否对js文件进行检查
示例:
- ```json
"compilerOptions": {
"allowJs": true,
"checkJs": true
}
```
- removeComments
- 是否删除注释
- 默认值:false
- noEmit
- 不对代码进行编译
- 默认值:false
- sourceMap
- 是否生成sourceMap
- 默认值:false
- 严格检查
- 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, веб-пакет
-
Обычно в реальной разработке нам необходимо использовать инструменты сборки для упаковки кода. TS также можно использовать в сочетании с инструментами сборки. Давайте возьмем веб-пакет в качестве примера, чтобы представить, как использовать TS в сочетании с инструментами сборки.
-
шаг:
-
Инициализировать проект
- Войдите в корневой каталог проекта и выполните команду
npm init -y
- Основная функция: создать файл package.json.
- Войдите в корневой каталог проекта и выполните команду
-
Загрузите инструменты сборки
npm i -D webpack webpack-cli webpack-dev-server typescript ts-loader clean-webpack-plugin
- Всего установлено 7 пакетов.
- веб-пакет
- Веб-пакет инструментов сборки
- вебпак-кли
- инструмент командной строки веб-пакета
- веб-пакет-dev-сервер
- сервер разработки веб-пакетов
- машинопись
- ts-компилятор
- ts-загрузчик
- ts-загрузчик для компиляции ts-файлов в веб-пакет
- html-webpack-плагин
- Плагин HTML в веб-пакете, используемый для автоматического создания файлов HTML.
- чистый-webpack-плагин
- Плагин очистки в веб-пакете сначала очищает каталог при каждой сборке.
- веб-пакет
- Всего установлено 7 пакетов.
-
Создайте файл конфигурации веб-пакета 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测试' }), ] }
-
-
Создайте tsconfig.json в корневом каталоге. Конфигурация может быть основана на ваших собственных потребностях.
-
{ "compilerOptions": { "target": "ES2015", "module": "ES2015", "strict": true } }
-
-
Измените package.json и добавьте следующую конфигурацию.
-
{ ...略... "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack", "start": "webpack serve --open chrome.exe" }, ...略... }
-
-
Создайте файл ts в src и выполните его в командной строке
npm run build
для компиляции кода или выполнитеnpm start
для запуска сервера разработки а >
-
5, Вавилон
-
После серии конфигураций TS и веб-пакет были объединены. Помимо веб-пакета, разработку также часто необходимо объединить с Babel для преобразования кода, чтобы он был совместим с большим количеством браузеров. На основе вышеуказанных шагов, с помощью следующих шаги введут Babel в проект.
-
Установите пакеты зависимостей:
npm i -D @babel/core @babel/preset-env babel-loader core-js
- Всего установлено 4 пакета, а именно:
- @babel/core
- Основные инструменты Babel
- @babel/preset-env
- Предопределенная среда Babel
- @babel-loader
- загрузчик Babel в веб-пакете
- ядро-js
- Core-js используется для того, чтобы старые браузеры поддерживали новый синтаксис ES.
- @babel/core
-
Измените файл конфигурации webpack.config.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/ } ] } ...略...
"ie": "11" }, "corejs":"3", "useBuiltIns": "usage" } ] ] } }, { loader: "ts-loader", } ], exclude: /node_modules/ } ]
… опущено… -
Таким образом, файлы, скомпилированные с использованием ts, будут снова обработаны Babel, так что код можно будет использовать непосредственно в большинстве браузеров.Вы можете указать совместимую версию браузера в целях параметров конфигурации.
-
-
объектно-ориентированный
Объектно-ориентированность — очень важная идея в программировании.Многие студенты понимают ее как сложную и глубокую проблему, но это не так. Объектно-ориентированный подход очень прост: короче говоря, все операции в программе необходимо выполнять через объекты.
- например:
- Для управления браузером используйте объект window
- Для управления веб-страницей используйте объект документа
- Для управления консолью используйте объект console
Все операции должны проходить через объекты, что является так называемой объектно-ориентированной.Так что же такое объекты? Давайте сначала поговорим о том, что такое программа.Сущность компьютерной программы – это абстракция реальных вещей.Антоним абстракции – конкретный.Например, фотография – это абстракция конкретного человека, модель автомобиля – это абстракция какого-либо конкретный автомобиль и т. д. Программа — это тоже абстракция вещей.В программе мы можем представлять человека, собаку, пистолет, пулю и т. д. Когда вещь входит в программу, она становится объектом.
Все объекты в программе разделены на две части: данные и функции.На примере людей к данным относятся имя человека, пол, возраст, рост, вес и т. д. Люди могут говорить, ходить, есть, спать и т. д. ., которые относятся к функциям человека. . Данные называются свойствами объекта, а функциональные возможности называются методами. Короче говоря, все в программе является объектом.
1. Класс
Если вы хотите быть объектно-ориентированным и работать с объектами, сначала у вас должны быть объекты, а затем следующий вопрос: как создавать объекты. Чтобы создать объект, необходимо сначала определить класс.Под так называемым классом можно понимать модель объекта.В программе вы можете создавать объекты заданных типов на основе класса.Например: вы можете создавать человека объекты с помощью класса Person и создания собак с помощью класса Dog. Объекты автомобилей создаются с помощью класса Car. Для создания разных объектов можно использовать разные классы.
-
Определить класс:
class 类名 { 属性名: 类型; constructor(参数: 类型){ this.属性名 = 参数; } 方法名(){ .... } }
Пример:
-
class Person{ name: string; age: number; constructor(name: string, age: number){ this.name = name; this.age = age; } sayHello(){ console.log(`大家好,我是${ this.name}`); } }
-
Используйте класс:
-
const p = new Person('孙悟空', 18); p.sayHello();
-
2. Объектно-ориентированные характеристики
-
инкапсуляция
-
Объект по сути является контейнером для свойств и методов. Его основная функция — хранить свойства и методы. Это называется инкапсуляцией.
-
По умолчанию атрибуты объекта могут быть изменены произвольно.Чтобы обеспечить безопасность данных, разрешения атрибутов могут быть установлены в TS.
-
Атрибуты только для чтения (только для чтения):
- Если вы добавите свойство только для чтения при объявлении свойства, свойство станет доступным только для чтения и не может быть изменено.
-
Свойства в TS имеют три модификатора:
- общедоступный (значение по умолчанию), может быть изменен в классах, подклассах и объектах
- защищен, может быть изменен в классах и подклассах
- частный, может быть изменен в классе
Пример:
-
общественный
-
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 = '猪八戒';// 可以通过对象修改
-
-
защищенный
-
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 = '猪八戒';// 不能修改
-
-
частный
-
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 = '猪八戒';// 不能修改
-
-
средство доступа к свойству
-
Для некоторых свойств, которые вы не хотите произвольно изменять, вы можете сделать их частными.
-
Установка его непосредственно в частный приведет к тому, что свойства в нем больше не смогут быть изменены через объект.
-
Мы можем определить в классе набор методов для чтения и установки свойств.Такой тип свойств, которые читают или устанавливают свойства, называется средством доступа к свойству.
-
Метод чтения атрибутов называется методом установки, а метод установки атрибутов называется методом получения.
Пример:
-
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('孙悟空'); console.log(p1.name); // 通过getter读取name属性 p1.name = '猪八戒'; // 通过setter修改name属性
-
-
статические свойства
-
Статические свойства (методы), также известные как свойства класса. При использовании статических свойств нет необходимости создавать экземпляр, их можно использовать напрямую через классы.
-
Статические свойства (методы) начинаются со static.
Пример:
-
class Tools{ static PI = 3.1415926; static sum(num1: number, num2: number){ return num1 + num2 } } console.log(Tools.PI); console.log(Tools.sum(123, 456));
-
-
этот
- В классе используйте это для представления текущего объекта
-
-
наследовать
-
Наследование — еще одна особенность объектно-ориентированного подхода.
-
Свойства и методы других классов могут быть введены в текущий класс посредством наследования.
Пример:
-
class Animal{ name: string; age: number; constructor(name: string, age: number){ this.name = name; this.age = age; } } class Dog extends Animal{ bark(){ console.log(`${ this.name}在汪汪叫!`); } } const dog = new Dog('旺财', 4); dog.bark();
-
-
Наследование позволяет расширять класс, не изменяя его.
-
переписать
- Когда происходит наследование, если метод в подклассе заменяет метод с тем же именем в родительском классе, это называется переопределением метода.
Пример:
-
class Animal{ name: string; age: number; constructor(name: string, age: number){ this.name = name; this.age = age; } run(){ console.log(`父类中的run方法!`); } } class Dog extends Animal{ bark(){ console.log(`${ this.name}在汪汪叫!`); } run(){ console.log(`子类中的run方法,会重写父类中的run方法!`); } } const dog = new Dog('旺财', 4); dog.bark();
-
Вы можете использовать super в подклассе, чтобы завершить ссылку на родительский класс.
-
абстрактный класс
-
Абстрактный класс — это класс, специально разработанный для наследования другими классами. Он может наследоваться только другими классами и не может использоваться для создания экземпляров.
-
abstract class Animal{ abstract run(): void; bark(){ console.log('动物在叫~'); } } class Dog extends Animals{ run(){ console.log('狗在跑~'); } }
-
Методы, начинающиеся с абстрактных, называются абстрактными методами.Абстрактные методы без тел методов могут быть определены только в абстрактных классах.При наследовании абстрактных классов необходимо реализовать абстрактные методы.
-
-
3. Интерфейс
Функция интерфейса аналогична функции абстрактного класса. Разница в том, что все методы и свойства интерфейса не имеют реального значения. Другими словами, все методы интерфейса являются абстрактными методами. Интерфейс в основном отвечает за определение структуры класса.Интерфейс может ограничивать интерфейс объекта.Объект может соответствовать интерфейсу только в том случае, если он содержит все свойства и методы, определенные в интерфейсе. В то же время классу может быть разрешено реализовать интерфейс.При реализации интерфейса класс должен защищать все свойства в интерфейсе.
Пример (проверка типа объекта):
-
interface Person{ name: string; sayHello():void; } function fn(per: Person){ per.sayHello(); } fn({ name:'孙悟空', sayHello() { console.log(`Hello, 我是 ${ this.name}`)}});
Пример (реализация)
-
interface Person{ name: string; sayHello():void; } class Student implements Person{ constructor(public name: string) { } sayHello() { console.log('大家好,我是'+this.name); } }
4. Общий
При определении функции или класса в некоторых случаях невозможно определить конкретные типы, которые будут использоваться (невозможно определить типы возвращаемых значений, параметров и свойств), и в этом случае в игру могут вступить дженерики.
-
например:
-
function test(arg: any): any{ return arg; }
-
В приведенном выше примере тестовая функция имеет параметр, тип которого неизвестен, но когда его можно определить, тип возвращаемого значения и тип параметра совпадают. Поскольку тип неопределенен, для обоих используется любой параметр и возвращаемое значение, но очевидно, что так сделано Нецелесообразно.Во-первых, использование Any отключит проверку типа TS.Во-вторых, эта настройка не может отражать, что параметры и возвращаемые значения одинаковы. тип.
-
Используйте дженерики:
-
function test<T>(arg: T): T{ return arg; }
-
Здесь
<T>
— универсальный тип. T — имя, которое мы даем этому типу (его не обязательно называть T). После установки универсального типа вы можете использовать T для представить его в функции типа. Так что дженерики на самом деле легко понять, они представляют определенный тип. -
Итак, как использовать вышеуказанную функцию?
Способ 1 (прямое использование):
-
test(10)
-
Вы можете напрямую передавать параметры при его использовании, и тип будет автоматически выведен TS. Однако иногда необходимо использовать следующий метод, когда компилятор не может автоматически определить его.
Способ 2 (укажите тип):
-
test<number>(10)
-
Вы также можете вручную указать дженерики после функции.
-
-
Одновременно можно указать несколько дженериков, разделив их запятыми:
-
function test<T, K>(a: T, b: K): K{ return b; } test<number, string>(10, "hello");
-
При использовании дженериков вы можете использовать дженерик как обычный класс.
-
-
Дженерики также можно использовать в классах:
-
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; }
-
Использование T расширяет MyInter означает, что общий T должен быть подклассом MyInter. Он не обязательно должен быть классом интерфейса или абстрактным классом. Это также применимо.
-
-