2019 年开始使用 TypeScript 2019 年开始使用 TypeScript

2025-05-26

2019 年开始使用 TypeScript

2019 年开始使用 TypeScript

2019 年开始使用 TypeScript

最初发布在我的博客上

根据2018 年 Stack Overflow 开发者调查,TypeScript 作为编程语言比 JavaScript 更受“喜爱”。TypeScript 之所以受到 JavaScript 开发者的青睐,是因为在 JavaScript 中添加类型可以让你在运行代码之前发现错误。TypeScript 编译器提供的错误信息可以很好地指导如何修复错误。添加类型还能让代码编辑器提供一些更高级的功能,例如代码补全、项目范围的重构和自动模块导入。

2018 年 Stack Overflow 调查中最受欢迎的编程语言调查问题结果2018 年 Stack Overflow 开发者调查中“最喜爱的编程语言”调查问题的结果

如果您将 TypeScript 视为一门全新的编程语言,学习它可能会令人望而生畏。然而,TypeScript 只是 JavaScript 的附加层,您无需了解 TypeScript 的所有语法即可开始使用。TypeScript 允许您轻松地将 JavaScript 文件转换为 TypeScript,只需将文件扩展名从 更改为 即可.js.ts所有代码都将正确编译为 TypeScript。如果您想在 TypeScript 文件中强制执行更大比例的类型覆盖,可以配置 TypeScript 以进行更严格的限制,但这只有在您更熟悉该语言后才能实现。

本文旨在帮助您快速掌握在标准 TypeScript 项目中通常会遇到的大约95% 的场景。对于剩下的 5%,Google 是您的好朋友,我在文章底部添加了一些有用的 TypeScript 资源链接。


设置 TypeScript

当然,要开始编写正确编译的 TypeScript,需要一个正确配置的开发环境。

1.安装 TypeScript 编译器

首先,需要安装 TypeScript 编译器,以便将 TypeScript 文件转换为 JavaScript 文件。TypeScript 可以全局安装(可在文件系统的任何位置使用),也可以本地安装(仅在项目级别使用)。

# NPM Installation Method

npm install --global typescript # Global installation
npm install --save-dev typescript # Local installation

# Yarn Installation Method

yarn global add typescript # Global installation
yarn add --dev typescript # Local installation
Enter fullscreen mode Exit fullscreen mode

从命令行运行的命令,用于在计算机上全局或本地安装 TypeScript

2. 确保你的编辑器支持 TypeScript

您需要确保您的编辑器已正确配置,可以使用 TypeScript。例如,您可能需要安装一个插件(例如,如果使用 Atom 编辑器,则需要安装atom-typescript),以便在编辑器中充分利用 TypeScript。如果您使用 VS Code,则 TypeScript 支持是内置的,因此无需任何扩展 😎。

3.创建 **tsconfig.json** 文件

tsconfig.json文件用于配置 TypeScript 项目设置。该tsconfig.json文件应放在项目的根目录中。该文件允许您使用不同的选项配置 TypeScript 编译器。

tsconfig.json如果您只想让 TypeScript 工作,则可以包含一个空的 JSON 对象,但如果您需要 TypeScript 编译器表现出不同的行为(例如在特定的输出目录中输出转换后的 JavaScript 文件),您可以阅读有关可以配置哪些设置的更多信息。

注意:您还可以运行_tsc --init_生成一个_tsconfig.json_文件,其中设置了一些默认选项,并注释掉了一些其他选项

4. 将 TypeScript 转换为 JavaScript

为了将 TypeScript 代码转译为 JavaScript,tsc需要在终端中运行该命令。运行该命令后,tscTypeScript 编译器会搜索该tsconfig.json文件,该文件将确定项目的根目录以及在编译 TypeScript 和将.ts文件转译为.js文件时要使用的选项。

为了快速测试设置是否有效,您可以创建一个测试 TypeScript 文件,然后tsc在命令行中运行并查看 TypeScript 文件旁边是否生成了 JavaScript 文件。

例如,这个 TypeScript 文件...

const greeting = (person: string) => {
    console.log('Good day ' + person);
};

greeting('Daniel');
Enter fullscreen mode Exit fullscreen mode

TypeScript 语法示例

应该转换为这个 JavaScript 文件...

var greeting = function(person) {
    console.log('Good day ' + person);
};

greeting('Daniel');
Enter fullscreen mode Exit fullscreen mode

通过转换 TypeScript 生成的 JavaScript 文件

如果您希望 TypeScript 编译器监视 TypeScript 文件中的更改并自动触发文件的转换.ts,您可以在项目的存储库中.js运行. 命令。tsc -p

在 VS Code 中,您可以使用⌘⇧B调出一个菜单,该菜单可以在正常模式或监视模式(分别为 或 )下运行转译tsc:buildtsc:watch

可以使用 ⌘⇧B 调出的 VS Code 构建任务菜单VS Code 构建任务菜单可以使用⌘⇧B


理解静态和动态类型

JavaScript 有 7 种动态类型:

  • 不明确的
  • 无效的
  • 布尔值
  • 数字
  • 细绳
  • 象征
  • 目的

上述类型被称为动态的,因为它们是在运行时使用的。

TypeScript 将静态类型引入 JavaScript 语言,这些类型在编译时进行评估(无需运行代码)。静态类型可以预测动态类型的值,这可以在无需运行代码的情况下提醒您可能遇到的错误。


基本静态类型

好了,让我们深入研究一下 TypeScript 的语法。以下是 TypeScript 中最常见的类型。

注意:我省略了_never__object_类型,因为根据我的经验,它们并不常用。

boolean

您所了解和喜爱的简单true和价值观。false

let isAwesome: boolean = true;
Enter fullscreen mode Exit fullscreen mode

布尔类型注释

string

用单引号 ( ')、双引号 ( ") 或反引号括起来的文本数据。

let name: string = 'Chris';
let breed: string = 'Border Collie';
Enter fullscreen mode Exit fullscreen mode

字符串类型注解

如果使用反引号,则该字符串称为模板文字,并且可以在其中插入表达式。

let punchline: string = 'Because it was free-range.';
let joke: string = `
    Q: Why did the chiken cross the road?
    A: ${punchline}
`;
Enter fullscreen mode Exit fullscreen mode

使用模板文字进行字符串类型注释

number

任何浮点数都被赋予 的类型number。TypeScript支持四种类型的数字字面量:十进制二进制八进制十六进制

let decimalNumber: number = 42;
let binaryNumber: number = 0b101010; // => 42
let octalNumber: number = 0o52; // => 42
let hexadecimalNumber: number = 0x2a; // => 42
Enter fullscreen mode Exit fullscreen mode

数字类型注释

注意:如果二进制、八进制和十六进制数让您感到困惑,那么您并不孤单。

array

TypeScript 中的数组类型可以用两种方式编写。第一种方式需要[]将 添加到数组中找到的元素的类型后缀。

let myPetFamily: string[] = ['rocket', 'fluffly', 'harry'];
Enter fullscreen mode Exit fullscreen mode

使用方括号表示法的字符串数组

编写类型的另一种方法Array是使用 Array,后跟数组中找到的元素的类型(在尖括号内)。

let myPetFamily: Array<string> = ['rocket', 'fluffly', 'harry'];
Enter fullscreen mode Exit fullscreen mode

使用尖括号表示法的字符串数组

tuple

Atuple是一个包含固定数量元素和相关类型的数组。

let myFavoriteTuple: [string, number, boolean];

myFavoriteTuple = ['chair', 20, true]; // ✅
myFavoriteTuple = [5, 20, true]; // ❌ - The first element should be a string, not a number
Enter fullscreen mode Exit fullscreen mode

声明一个包含 3 个元素的元组,然后为该元组赋值

enum

枚举enum是一种将名称与常量值关联起来的方法,该常量值可以是数字或字符串。当你需要一组具有描述性名称的不同值时,枚举非常有用。

默认情况下,枚举会分配从 开始的数字,0并且1枚举的每个成员都会增加 。

enum Sizes {
    Small,
    Medium,
    Large,
}

Sizes.Small; // => 0
Sizes.Medium; // => 1
Sizes.Large; // => 2
Enter fullscreen mode Exit fullscreen mode

从 9 开始的枚举示例

第一个值可以设置为除 之外的值0

enum Sizes {
    Small = 1,
    Medium,
    Large,
}

Sizes.Small; // => 1
Sizes.Medium; // => 2
Sizes.Large; // => 3
Enter fullscreen mode Exit fullscreen mode

枚举从非 0 值开始的示例

枚举默认分配有数字,但是也可以将字符串值分配给枚举。

enum ThemeColors {
    Primary = 'primary',
    Secondary = 'secondary',
    Dark = 'dark',
    DarkSecondary = 'darkSecondary',
}
Enter fullscreen mode Exit fullscreen mode

具有字符串值的枚举示例

any

如果变量的类型未知,并且我们不希望类型检查器在编译时发出抱怨,那么any可以使用的类型。

let whoKnows: any = 4; // assigned a number

whoKnows = 'a beautiful string'; // can be reassigned to a string
whoKnows = false; // can be reassigned to a boolean
Enter fullscreen mode Exit fullscreen mode

any 类型的示例

any在开始使用 TypeScript 时,它可能会经常被使用。但是,最好尽量减少它的使用,any因为当编译器无法识别变量关联的类型时,TypeScript 的实用性会降低。

void

当没有与任何类型关联的对象时,void应该使用该类型。它最常用于指定不返回任何内容的函数的返回值。

const darkestPlaceOnEarth = (): void => {
    console.log('Marianas Trench');
};
Enter fullscreen mode Exit fullscreen mode

使用 void 类型的示例

nullundefined

和 都null对应于 JavaScript 中常见的和值undefined的类型。这些类型单独使用时用处不大。nullundefined

let anUndefinedVariable: undefined = undefined;
let aNullVariable: null = null;
Enter fullscreen mode Exit fullscreen mode

如何使用 null 和 undefined 类型的示例

默认情况下,nullundefined类型是所有其他类型的子类型,这意味着类型为 的变量string可以被赋值为nullundefined。这通常是不受欢迎的行为,因此通常建议strictNullCheckstsconfig.json文件中将编译器选项设置为true。将选项设置strictNullCheckstrue,则需要将nullundefined明确设置为变量的类型。


类型推断

幸运的是,你不必在代码的任何地方都绝对指定类型,因为 TypeScript 具有所谓的类型推断。类型推断是 TypeScript 编译器用来自动确定类型的方法。

基本类型推断

TypeScript 可以在变量初始化、设置默认参数值以及确定函数返回值时推断类型。

// Variable initialization
let x = 10; // x is given the number type
Enter fullscreen mode Exit fullscreen mode

类型推断的示例,其中 x 变量具有推断的数字类型

在上面的例子中,x被分配了一个数字,TypeScript 将该x变量与 的类型关联起来number

// Default function parameters
const tweetLength = (message = 'A default tweet') => {
    return message.length;
};
Enter fullscreen mode Exit fullscreen mode

为消息参数提供推断类型的字符串

在上面的例子中,message参数被分配了一个默认值,该值的类型为string,因此 TypeScript 编译器推断出该message类型为,因此在访问string该属性时不会引发编译错误。length

function add(a: number, b: number) {
    return a + b;
}

const result = add(2, 4);

result.toFixed(2); // ✅
result.length; // ❌ - length is not a property of number types
Enter fullscreen mode Exit fullscreen mode

根据函数参数的类型,推断数字类型分配给 add 函数的返回值

在上面的例子中,由于 TypeScript 被告知函数的两个参数都add具有类型number,因此它可以推断返回类型也将是number

最佳通用类型推断

当从多种可能的类型中推断出一种类型时,TypeScript 使用“最佳通用类型”算法来选择一种适用于所有其他候选的类型。

let list = [10, 22, 4, null, 5];

list.push(6); // ✅
list.push(null); // ✅
list.push('nope'); // ❌ - type 'string' is neither of type 'number' or 'null'
Enter fullscreen mode Exit fullscreen mode

最佳通用类型算法确定只应允许数字和空类型作为列表数组的元素

在上面的例子中,数组由numbernull类型组成,因此 TypeScript 只期望numbernull值成为数组的一部分。


类型注解

当类型推断系统不够用时,您将需要在变量和对象上声明类型。

基本类型

基本静态类型部分介绍的所有类型都可以使用:后跟类型名称来声明。

let aBoolean: boolean = true;
let aNumber: number = 10;
let aString: string = 'woohoo';
Enter fullscreen mode Exit fullscreen mode

注释基本类型的示例

数组

如讨论类型的部分所示array,数组可以用两种方式之一进行注释。

// First method is using the square bracket notation
let messageArray: string[] = ['hello', 'my name is fred', 'bye'];

// Second method uses the Array keyword notation
let messageArray: Array<string> = ['hello', 'my name is fred', 'bye'];
Enter fullscreen mode Exit fullscreen mode

注释数组

接口

将多个类型注释组合在一起的一种方法是使用接口。

interface Animal {
    kind: string;
    weight: number;
}

let dog: Animal;

dog = {
    kind: 'mammal',
    weight: 10,
}; // ✅

dog = {
    kind: true,
    weight: 10,
}; // ❌ - kind should be a string
Enter fullscreen mode Exit fullscreen mode

使用接口注释类型

类型别名

为了使事情变得混乱,TypeScript 还允许您使用类型别名指定多个类型注释。

type Animal = {
    kind: string;
    weight: number;
};

let dog: Animal;

dog = {
    kind: 'mammal',
    weight: 10,
}; // ✅

dog = {
    kind: true,
    weight: 10,
}; // ❌ - kind should be a string
Enter fullscreen mode Exit fullscreen mode

使用类型别名注释类型

在使用接口或类型别名方面,最佳实践似乎是在代码库中只选择其中一种,interfacetype保持一致。但是,如果编写的是可供他人使用的第三方公共 API,则应使用interface类型。

如果您想更详细地比较类型别名和接口,我推荐Matin Hochel 的这篇文章

内联注释

与创建可重复使用的接口相比,用内联方式注释类型可能更合适。

let dog: {
    kind: string;
    weight: number;
};

dog = {
    kind: 'mammal',
    weight: 10,
}; // ✅

dog = {
    kind: true,
    weight: 10,
}; // ❌ - kind should be a string
Enter fullscreen mode Exit fullscreen mode

使用内联类型注释

泛型

在某些情况下,变量的具体类型并不重要,但需要强制不同变量的类型之间的关系。对于这些情况,应该使用泛型。

const fillArray = <T>(len: number, elem: T) => {
    return new Array<T>(len).fill(elem);
};

const newArray = fillArray<string>(3, 'hi'); // => ['hi', 'hi', 'hi']

newArray.push('bye'); // ✅
newArray.push(true); // ❌ - only strings can be added to the array
Enter fullscreen mode Exit fullscreen mode

使用泛型类型定义类型关系

上面的例子有一个泛型类型T,它对应于传递给函数的第二个参数的类型fillArray。传递给函数的第二个参数fillArray是一个字符串,因此创建的数组的所有元素都会被设置为 类型string

需要注意的是,按照惯例,泛型类型使用单个字母(例如TK)。但是,您可以使用更具描述性的名称来命名泛型类型。以下是上述示例,其中提供的泛型类型具有更具描述性的名称:

const fillArray = <ArrayElementType>(len: number, elem: ArrayElementType) => {
    return new Array<ArrayElementType>(len).fill(elem);
};

const newArray = fillArray<string>(3, 'hi'); // => ['hi', 'hi', 'hi']

newArray.push('bye'); // ✅
newArray.push(true); // ❌ - only strings can be added to the array
Enter fullscreen mode Exit fullscreen mode

对泛型使用更具描述性的名称

联合类型

在一种类型可以是多种类型之一的情况下,使用联合类型通过用 分隔不同的类型选项|

// The `name` parameter can be either a string or null
const sayHappyBirthdayOnFacebook = (name: string | null) => {
    if (name === null) {
        console.log('Happy birthday!');
    } else {
        console.log(`Happy birthday ${name}!`);
    }
};

sayHappyBirthdayOnFacebook(null); // => "Happy birthday!"
sayHappyBirthdayOnFacebook('Jeremy'); // => "Happy birthday Jeremy!"
Enter fullscreen mode Exit fullscreen mode

联合类型注释的示例

交叉口类型

交集类型使用&符号将多个类型组合在一起。这与联合类型不同,联合类型表示“结果类型是列出的类型之一”,而交集类型表示“结果类型是所有列出的类型的组合”。

type Student = {
    id: string;
    age: number;
};

type Employee = {
    companyId: string;
};

let person: Student & Employee;

person.age = 21; // ✅
person.companyId = 'SP302334'; // ✅
person.id = '10033402'; // ✅
person.name = 'Henry'; // ❌ - name does not exist in Student & Employee
Enter fullscreen mode Exit fullscreen mode

交叉类型注释的示例

元组类型

元组使用:方括号内以逗号分隔的类型列表进行注释。

let list: [string, string, number];

list = ['apple', 'banana', 8.75]; // ✅
list = ['apple', true, 8.75]; // ❌ - the second argument should be of type string
list = ['apple', 'banana', 10.33, 3]; // ❌ - the tuple specifies a length of 3, not 4
Enter fullscreen mode Exit fullscreen mode

使用元组类型注释变量

可选类型

在某些情况下,函数参数或对象属性可能是可选的。在这种情况下,?使用 a 来表示这些可选值。

// Optional function parameter
function callMom(message?: string) {
    if (!message) {
        console.log('Hi mom. Love you. Bye.');
    } else {
        console.log(message);
    }
}

// Interface describing an object containing an optional property
interface Person {
    name: string;
    age: number;
    favoriteColor?: string; // This property is optional
}
Enter fullscreen mode Exit fullscreen mode

定义可选类型


有用的资源

对于本文未涉及的 TypeScript 部分,我推荐以下资源。

TypeScript 手册(官方 TypeScript 文档)

TypeScript 深度探索(在线 TypeScript 指南)

理解 TypeScript 的类型注解(很棒的 TypeScript 入门文章)

文章来源:https://dev.to/robertcoopercode/get-started-with-typescript-in-2019-6hd
PREV
使用别名加速你的 Git 工作流程
NEXT
软件开发人员应遵循的四项安全原则