Это 84-я оригинальная статья без воды.Если вы хотите получить больше оригинальных статей, выполните поиск в официальном аккаунте и подпишитесь на нас~ Эта статья была впервые опубликована в блоге Zhengcaiyun:Написание высококачественного поддерживаемого кода: Awesome TypeScript
предисловие
Качественный и удобный в сопровождении код должен обладать такими характеристиками, как высокая читабельность, четкая структура, низкая связанность и простота расширения. Однако нативный JavaScript не подходит для разработки и сопровождения крупномасштабных приложений из-за его слабой типизации и отсутствия модульности, поэтому на свет появился TypeScript.
TypeScript — это надмножество JavaScript, предназначенное не для замены JavaScript, а для внесения ряда улучшений на основе JavaScript, включая добавление статических типов, интерфейсов, классов, обобщений, перегрузку методов и многое другое. Итак, если у вас есть определенные знания JavaScript, начать работу с TypeScript очень просто. И вы можете с удовольствием использовать синтаксис JavaScript в TypeScript.
Далее в этой статье мы поделимся с вами важными функциями TypeScript и навыками использования в практических сценариях, которые помогут вам более эффективно писать высококачественный и удобный для сопровождения код.
Typescript VS Javascript
JavaScript
- JavaScript — это язык с динамической типизацией, и переменные не проверяются на тип на этапе компиляции кода, что приводит к потенциальным ошибкам типов на этапе выполнения кода. А при столкновении с присваиваниями разных типов переменных преобразование типов будет выполняться автоматически, что вносит неопределенность и чревато ошибками.
- JavaScript изначально не имеет пространств имен, и вам нужно вручную создавать пространства имен для модульности. Кроме того, JavaScript позволяет дублировать определения функций с одинаковыми именами, а более поздние определения могут переопределять более ранние. Это также создает неудобства при разработке и обслуживании крупномасштабных приложений.
TypeScript
- TypeScript — это статически типизированный язык, обеспечивающий статическую проверку типов во время компиляции с помощью аннотаций типов.
- Обнаружение типа переменной выполняется на этапе компиляции кода, чтобы заранее выявить потенциальные ошибки типа. А на этапе выполнения кода не допускается присваивание между переменными разных типов.
- Аннотации понятных типов не только делают код более читабельным, но и расширяют возможности среды IDE, включая завершение кода, подсказки интерфейса, переход к определениям и многое другое.
- TypeScript добавляет типы модулей и собственное пространство имен, что облегчает модульную разработку крупномасштабных приложений.
- TypeScript разработан как полностью объектно-ориентированный язык программирования с модулями, интерфейсами, классами, аннотациями типов и т. д., которые могут сделать нашу структуру организации кода более понятной.
После приведенного выше сравнения мы видим, что появление TypeScript компенсировало некоторые дефекты дизайна JavaScript, принесло нам большое удобство и повысило надежность и масштабируемость кода.
Важные особенности
тип данных
-
Основные типы данных включают в себя: Boolean, Number, String, Array, Enum, Any, Unknown, Tuple, Void, Null, Undefined, Never. Давайте выберем несколько специфичных для TypeScript типов для подробного объяснения:
- Перечисление перечисления: в процессе кодирования необходимо избегать жесткого кодирования.Если константа может быть перечислена одна за другой, рекомендуется использовать тип перечисления для ее определения, что может упростить поддержку кода.
// 包括 数字枚举、字符串枚举、异构枚举(数字和字符串的混合)。 // 数字枚举在不设置默认值的情况下,默认第一个值为0,其他依次自增长 enum STATUS { PENDING, PROCESS, COMPLETED, } let status: STATUS = STATUS.PENDING; // 0
- Любой тип: не рекомендуется. Тип Any является типом верхнего уровня, и все типы можно рассматривать как любой тип.Использование Any эквивалентно отключению механизма проверки типов TypeScript.
- Неизвестный тип: Неизвестный тип также является типом верхнего уровня, он может принимать любой тип, но отличается от Any тем, что определяет тип данных после первого присваивания, и не позволяет изменить тип данных переменной дважды. Поэтому в сценариях, где вам нужно получить все типы, предпочтительнее использовать Unknown вместо Any.
- Кортеж: поддерживает хранение элементов разных типов данных в массиве, что позволяет нам быть более гибкими при организации данных.
let tupleType: [string, boolean]; tupleType = ["momo", true];
- Тип Void: когда функция не имеет возвращаемого значения, тип возвращаемого значения функции обычно устанавливается равным void.
введите аннотацию
- TypeScript обеспечивает статическую проверку типов во время компиляции с помощью аннотаций типов, которые могут найти потенциальные ошибки на этапе компиляции и сделать подсказки в процессе кодирования более интеллектуальными. Он прост в использовании, в
:
Вы можете указать тип переменной после двоеточия.
const str: string = 'abc';
интерфейс
- Внутри объектно-ориентированного программирования интерфейс является ключом к реализации развязки программы, которая только определяет, какие атрибуты и методы включены, без каких-либо конкретных деталей реализации. Интерфейс основан на классе, дополнительных абстрактных сущностях или поведении, что позволяет программе иметь лучшую масштабируемость.
- Сценарий приложений: Например, когда мы реализуем функции, связанные с заказами, нам нужно абстрактное порядок, определить интерфейс заказа, включая базовую информацию о заказе и связанные с ними операции, а затем дополнительно реализовывать на основе этого интерфейса. Если связанная функция операции изменений заказа в будущем нужно только переопределить класс для реализации этого интерфейса.
interface Animal {
name: string;
getName(): string;
}
class Monkey implements Padder {
constructor(private name: string) {
getName() {
return 'Monkey: ' + name;
}
}
}
Добрый
- В дополнение к включению самых основных свойств и методов, геттеров и сеттеров, наследования и других функций, классы TypeScript также добавляют частные поля. К закрытым полям нельзя получить доступ за пределами содержащего класса или даже обнаружить. В классах Javascript нет частных полей.Если вы хотите имитировать частные поля, вы должны использовать замыкания для их имитации. Вот несколько примеров, иллюстрирующих использование следующих классов:
- свойства и методы
class Person {
// 静态属性
static name: string = "momo";
// 成员属性
gender: string;
// 构造函数
constructor(str: string) {
this.gender = str;
}
// 静态方法
static getName() {
return this.name;
}
// 成员方法
getGender() {
return 'Gender: ' + this.gender;
}
}
let person = new Person("female");
- геттеры и сеттеры
- Инкапсуляция данных и проверка достоверности реализованы с помощью методов получения и установки для предотвращения появления аномальных данных.
class Person {
private _name: string;
get name(): string {
return this._name;
}
set name(newName: string) {
this._name = newName;
}
}
let person = new Person('momo');
console.log(person.name); // momo
person.name = 'new_momo';
console.log(person.name); // new_momo
- наследовать
class Animal {
name: string;
constructor(nameStr=:string) {
this.name = nameStr;
}
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) {
super(name);
}
move(distanceInMeters = 5) {
super.move(distanceInMeters);
}
}
let snake = new Snake('snake');
snake.move(); // 输出:'snake moved 5m'
- частное поле
- Частные поля начинаются с
#
начинается персонаж. К закрытым полям нельзя получить доступ за пределами содержащего класса или даже обнаружить.
- Частные поля начинаются с
class Person {
#name: string;
constructor(name: string) {
this.#name = name;
}
greet() {
console.log(`Hello, ${this.#name}!`);
}
}
let person = new Person('momo');
person.#name; // 访问会报错
Дженерики
-
Сценарий приложения: универсальные шаблоны используются, когда нам нужно учитывать возможность повторного использования кода. Включите компоненты для поддержки не только текущих типов данных, но и будущих типов данных. Универсальные шаблоны позволяют одной и той же функции принимать параметры разных типов.По сравнению с использованием типа Any компоненты, созданные с помощью универсальных шаблонов, более пригодны для повторного использования и расширяются, поскольку универсальные шаблоны сохраняют типы параметров. Дженерики могут применяться к интерфейсам, классам, переменным. Вот несколько примеров, иллюстрирующих использование дженериков:
-
общий интерфейс
interface identityFn<T> { (arg: T): T; }
-
общий класс
class GenericNumber<T> { zeroValue: T; add: (x: T, y: T) => T; } let myGenericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function (x, y) { return x + y; };
-
Общая переменная
Типовые переменные, определенные заглавными буквами от A до Z, являются универсальными.
- T (тип): представляет тип TypeScript.
- K (ключ): представляет тип ключа в объекте.
- V (значение): представляет тип значения в объекте.
- E (Элемент): указывает тип элемента
перекрестный тип
- Кросс-тип — это объединение нескольких типов в один тип. пройти через
&
определение оператора. В следующем примере тип Person и тип Company объединяются для создания нового типа Staff, в котором есть все члены обоих типов.
interface Person {
name: string;
gender: string;
}
interface Company {
companyName: string;
}
type Staff = Person & Company;
const staff: Staff = {
name: 'momo',
gender: 'female',
companyName: 'ZCY'
};
тип объединения
- Тип объединения — это комбинация нескольких типов с отношением ИЛИ, если выполняется один из них. пройти через
|
определение оператора. В следующем примере входной параметр функции может иметь строковый или числовой тип.
function fn(param: string | number): void {
console.log("This is the union type");
}
защита типа
-
Защита типа заключается в безопасном вызове свойств и методов, соответствующих этому типу данных, когда мы определили, что текущие данные относятся к определенному типу данных. Общие виды защиты включают
in
тип защиты,typeof
тип защиты,instanceof
защита типа и自定义
Защита типа. Подробности смотрите в следующих примерах:-
in
защита типа
interface Person { name: string; gender: string; } interface Employee { name: string; company: string; } type UnknownStaff = Person | Employee; function getInfo(staff: UnknownStaff) { if ("gender" in staff) { console.log("Person info"); } if ("company" in staff) { console.log("Employee info"); } }
-
typeof
защита типа
function processData(param: string | number): unknown { if (typeof param === 'string') { return param.toUpperCase() } return param; }
-
instanceof
Защита типа: иtypeof
Аналогичный тип использования, он в основном используется для определения того, является ли объект объектом класса или унаследованным.
function processData(param: Date | RegExp): unknown { if (param instanceof Date) { return param.getTime(); } return param; }
-
自定义
Защита типа: через предикат типаparameterName is Type
для реализации пользовательской защиты типа. В следующем примере реализована защита типа параметров запроса интерфейса.
interface ReqParams { url: string; onSuccess?: () => void; onError?: () => void; } // 检测 request 对象包含参数符合要求的情况下,才返回 url function validReqParams(request: unknown): request is ReqParams { return request && request.url }
-
советы по развитию
- Необходимо постоянно судить о том, есть ли в объекте определенный атрибут глубокого уровня, вы можете использовать
?.
if(result && result.data && result.data.list) // JS
if(result?.data?.list) // TS
- Чтобы совместно судить, является ли это нулевым значением, вы можете использовать
??
let temp = (val !== null && val !== void 0 ? val : '1'); // JS
let temp = val ?? '1'; // TS
-
Не полагайтесь исключительно на проверку типов и при необходимости пишите защитный код.
- Поскольку ошибка типа не повлияет на генерацию и выполнение кода, в принципе существует возможность вызова fn('str'), поэтому для защитного кода необходимо значение по умолчанию.
function fn(value:boolean){
switch(value){
case true:
console.log('true');
break;
case false:
console.log('false');
break;
default:
console.log('dead code');
}
}
- Для функций строго контролируйте тип возвращаемого значения.
// 推荐写法
function getLocalStorage<T>(key: string): T | null {
const str = window.localStorage.getItem(key);
return str ? JSON.parse(str) : null;
}
const data = getLocalStorage<DataType>("USER_KEY");
-
Реализация фабричного шаблона с помощью new()
- Синтаксис TypeScript для реализации фабричного шаблона очень прост: вам нужно только сначала определить функцию, объявить параметр типа конструктора, а затем вернуть объект, созданный классом c, в теле функции. В следующем примере фабричная функция создает объект типа T.
function create<T>(c: { new(): T }): T {
return new c();
}
class Test {
constructor() {
}
}
create(Test);
-
Предпочитать неизвестный тип любому
-
Используйте только для чтения, чтобы пометить входные параметры, чтобы гарантировать, что параметры не будут изменены внутри функции.
function fn(arr:readonly number[] ){
let sum=0, num = 0;
while((num = arr.pop()) !== undefined){
sum += num;
}
return sum;
}
- Используйте Enum для поддержки постоянной таблицы для более безопасной проверки типов.
// 使用 const enum 维护常量
const enum PROJ_STATUS {
PENDING = 'PENDING',
PROCESS = 'PROCESS',
COMPLETED = 'COMPLETED'
}
function handleProject (status: PROJ_STATUS): void {
}
handleProject(PROJ_STATUS.COMPLETED)
- Рекомендуется включить следующие параметры проверки компиляции, чтобы облегчить обнаружение потенциальных ошибок в среде компиляции.
{
"compilerOptions": {
/* 严格的类型检查选项 */
"strict": true, // 启用所有严格类型检查选项
"noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错
"strictNullChecks": true, // 启用严格的 null 检查
"noImplicitThis": true, // 当 this 表达式值为 any 类型的时候,生成一个错误
"alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict'
/* 额外的检查 */
"noUnusedLocals": true, // 有未使用的变量时,抛出错误
"noUnusedParameters": true, // 有未使用的参数时,抛出错误
"noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误
"noFallthroughCasesInSwitch": true,// 报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿)
}
}
Связанные плагины VSCode
Пакет расширений TypeScript, представляющий собой набор подключаемых модулей, связанных с TypeScript, которые мы используем каждый день:
- TSLint: автоматическое обнаружение и исправление несовместимого кода TypeScript.
- TypeScript Hero: Сортировка и организация порядка импорта модулей, удаление неиспользуемых модулей. Ярлыки в MacOS
Ctrl+Opt+o
, сочетания клавиш в Win/LinuxCtrl+Alt+o
. - json2ts: преобразование JSON из буфера обмена в интерфейс TypeScript. Ярлыки в MacOS
Ctrl+Opt+V
, сочетания клавиш в Win/LinuxCtrl+Alt+V
. - Переместить TS: при перемещении файлов TypeScript или папок, содержащих файлы TypeScript, пути импорта связанных зависимых модулей автоматически обновляются.
- Path Intellisense: автоподсказка для путей и имен файлов.
- Средство импорта TypeScript: при импорте модуля он автоматически ищет все экспортированные модули в текущей рабочей области и автоматически выполняет запрос.
- Prettier — средство форматирования кода: форматирование кода.
Рекомендуемое чтение
Саморазвитие фронтенд-инженеров: как React Fiber делает процесс обновления контролируемым
Утилизация мусора двигателя V8 и выделение памяти
Карьера
ZooTeam, молодая, увлеченная и творческая команда, связанная с отделом исследований и разработок продукции Zhengcaiyun, базируется в живописном Ханчжоу. В настоящее время в команде более 40 фронтенд-партнеров, средний возраст которых составляет 27 лет, и почти 30% из них — инженеры полного стека, настоящая молодежная штурмовая группа. В состав членов входят «ветераны» солдат из Ali и NetEase, а также первокурсники из Чжэцзянского университета, Университета науки и технологий Китая, Университета Хандянь и других школ. В дополнение к ежедневным деловым связям, команда также проводит технические исследования и фактические боевые действия в области системы материалов, инженерной платформы, строительной платформы, производительности, облачных приложений, анализа и визуализации данных, а также продвигает и внедряет ряд внутренних технологий. Откройте для себя новые горизонты передовых технологических систем.
Если вы хотите измениться, вас забрасывают вещами, и вы надеетесь начать их бросать; если вы хотите измениться, вам сказали, что вам нужно больше идей, но вы не можете сломать игру; если вы хотите изменить , у вас есть возможность добиться этого результата, но вы не нужны; если вы хотите изменить то, чего хотите достичь, вам нужна команда для поддержки, но вам некуда вести людей; если вы хотите изменить установившийся ритм, это будет "5 лет рабочего времени и 3 года стажа работы"; если вы хотите изменить исходный Понимание хорошее, но всегда есть размытие того слоя оконной бумаги.. , Если вы верите в силу веры, верьте, что обычные люди могут достичь необыкновенных вещей, и верьте, что они могут встретить лучшего себя. Если вы хотите участвовать в процессе становления бизнеса и лично способствовать росту фронтенд-команды с глубоким пониманием бизнеса, надежной технической системой, технологиями, создающими ценность, и побочным влиянием, я думаю, что мы должны говорить. В любое время, ожидая, пока вы что-нибудь напишете, отправьте это наZooTeam@cai-inc.com