TypeScript 终极初学者指南

网站建设3年前发布
65 0 0

20230306102128c823a8f53528a1492c4885a7206fdd971888a5657,下面是我整理的一些初学者必备的一些知识点~,2023030610212858ce2fd606c426cd224651aaf56367d2659817876,据官方描述:TypeScript 是 JavaScript 的超集,这意味着它可以完成 JavaScript 所做的所有事情,而且额外附带了一些能力。,JavaScript 本身是一种动态类型语言,这意味着变量可以改变类型。使用 TypeScript 的主要原因是就是为了给 JavaScript 添加静态类型。静态类型意味着变量的类型在程序中的任何时候都不能改变。它可以防止很多bug !,下面是学习 Typescript 的几个理由:,当然,使用 Typescript 也有一些缺点:,但是,相比于提前发现更多的 bug,花更长的时间也是值得的。,在 JavaScript 中,有 7 种原始类型:,原始类型都是不可变的,你可以为原始类型的变量重新分配一个新值,但不能像更改对象、数组和函数一样更改它的值。可以看下面的例子:,回到 TypeScript ,我们可以在声明一个变量之后设置我们想要添加的类型 :type (我们一般称之为“类型注释”或“类型签名”):,但是,如果变量有默认值的话,一般我们也不需要显式声明类型,TypeScript  会自动推断变量的类型(类型推断):,我们还可以将变量设置为联合类型(联合类型是可以分配多个类型的变量):,在 TypeScript 中,你可以定义数组包含的数据类型:,你也可以使用联合类型来定义包含多种类型的数组:,如果数组有默认值, TypeScript 同样也会进行类型推断:,TypeScript 中的对象必须拥有所有正确的属性和值类型:,在定义对象的类型时,我们通常会使用 interface。如果我们需要检查多个对象是否具有相同的特定属性和值类型时,是很有用的:,我们还可以用函数的类型签名声明一个函数属性,通用函数(sayHi)和箭头函数(sayBye)都可以声明:,需要注意的是,虽然 eat、speak 分别是用普通函数和箭头函数声明的,但是它们具体是什么样的函数类型都可以,Typescript 是不关心这些的。,我们可以定义函数参数和返回值的类型:,ES6 箭头函数的写法:,我们没必要明确声明 circle 是一个函数,TypeScript 会进行类型推断。TypeScript 还会推断函数的返回类型,但是如果函数体比较复杂,还是建议清晰的显式声明返回类型。,我们可以在参数后添加一个?,表示它为可选参数;另外参数的类型也可以是一个联合类型:,如果函数没有返回值,在 TS 里表示为返回 void,你也不需要显式声明,TS 一样可以进行类型推断:,使 any 类型,我们基本上可以将 TypeScript 恢复为 JavaScript:,如果代码里使用了大量的 any,那 TypeScript 也就失去了意义,所以我们应该尽量避免使用 any 。,使用非空断言运算符 (!),我们可以明确地告诉编译器一个表达式的值不是 null 或 undefined。当编译器无法准确地进行类型推断时,这可能很有用:,这里我们没必要声明 link 变量的类型。这是因为 TypeScript 可以通过类型推断确认它的类型为 HTMLAnchorElement。,但是如果我们需要通过 class 或 id 来选择一个 DOM 元素呢?这时 TypeScript 就没办法推断类型了:,我们需要告诉 TypeScript form 确定是存在的,并且我们知道它的类型是  HTMLFormElement。我们可以通过类型转换来做到这一点:,TypeScript 还内置了一个 Event 对象。如果我们在表单中添加一个 submit 的事件侦听器,TypeScript 可以自动帮我们推断类型错误:,我们可以定义类中每条数据的类型:,我们可以创建一个仅包含从 Person 构造的对象数组:,我们可以给类的属性添加访问修饰符,TypeScript 还提供了一个新的 readonly 访问修饰符。,我们可以通过下面的写法,属性会在构造函数中自动分配,我们类会更加简洁:,接口定义了对象的外观:,你还可以使用类型别名定义对象类型:,或者可以直接匿名定义对象类型:,interface 和 type 非常相似,很多情况下它俩可以随便用。比如它们两个都可以扩展:,扩展 interface:,扩展 type:,但是有个比较明显的区别,interface 是可以自动合并类型的,但是 type 不支持:,类型别名在创建后无法更改:,一般来说,当你不知道用啥的时候,默认就用 interface 就行,直到 interface 满足不了我们的需求的时候再用 type。,我们可以通过实现一个接口来告诉一个类它必须包含某些属性和方法:,确保 people 是一个实现 HasFormatter 的对象数组(确保每 people 都有 format 方法):,泛型可以让我们创建一个可以在多种类型上工作的组件,它能够支持当前的数据类型,同时也能支持未来的数据类型,这大大提升了组件的可重用性。我们来看下面这个例子:,addID 函数接受一个任意对象,并返回一个新对象,其中包含传入对象的所有属性和值,以及一个 0 到 1000 之间随机的 id 属性。,当我们尝试访问 name 属性时,TypeScript 会出错。这是因为当我们将一个对象传递给 addID 时,我们并没有指定这个对象应该有什么属性 —— 所以 TypeScript 不知道这个对象有什么属性。因此,TypeScript 知道的唯一属性返回对象的 id。,那么,我们怎么将任意对象传递给 addID,而且仍然可以告诉 TypeScript 该对象具有哪些属性和值?这种场景就可以使用泛型了, <T> – T 被称为类型参数:,这是啥意思呢?现在当我们再将一个对象传递给 addID 时,我们已经告诉 TypeScript 来捕获它的类型了 —— 所以 T 就变成了我们传入的任何类型。addID 现在会知道我们传入的对象上有哪些属性。,但是,现在有另一个问题:任何东西都可以传入 addID ,TypeScript 将捕获类型而且并不会报告问题:,当我们传入一个字符串时,TypeScript 没有发现任何问题。只有我们尝试访问 name 属性时才会报告错误。所以,我们需要一个约束:我们需要通过将泛型类型 T 作为 object 的扩展,来告诉 TypeScript 只能接受对象:,错误马上就被捕获了,完美…… 好吧,也不完全是。在 JavaScript 中,数组也是对象,所以我们仍然可以通过传入数组来逃避类型检查:,要解决这个问题,我们可以这样说:object 参数应该有一个带有字符串值的 name 属性:,泛型允许在参数和返回类型提前未知的组件中具有类型安全。,在 TypeScript 中,泛型用于描述两个值之间的对应关系。在上面的例子中,返回类型与输入类型有关。我们用一个泛型来描述对应关系。,另一个例子:如果需要接受多个类型的函数,最好使用泛型而不是 any 。下面展示了使用 any 的问题:,我们可以尝试使用泛型:,好,至少我们现在得到了一些反馈,可以帮助我们持续改进我们的代码。,解决方案:使用一个泛型来扩展一个接口,确保传入的每个参数都有一个 length 属性:,我们也可以编写这样一个函数,它的参数是一个元素数组,这些元素都有一个 length 属性:,泛型是 TypeScript 的一个很棒的特性!,当我们不知道对象中的某个值是什么类型时,可以使用泛型来传递该类型:,枚举是 TypeScript 给 JavaScript 带来的一个特殊特性。枚举允许我们定义或声明一组相关值,可以是数字或字符串,作为一组命名常量。,默认情况下,枚举是基于数字的 — 它们将字符串值存储为数字。但它们也可以是字符串:,当我们有一组相关的常量时,枚举就可以派上用场了。例如,与在代码中使用非描述性数字不同,枚举通过描述性常量使代码更具可读性。,枚举还可以防止错误,因为当你输入枚举的名称时,智能提示将弹出可能选择的选项列表。,建议在 tsconfig.json 中启用所有严格的类型检查操作文件。这可能会导致 TypeScript 报告更多的错误,但也更有助于帮你提前发现发现程序中更多的 bug。,在下面的函数中,TypeScript 已经推断出参数 a 是 any 类型的。当我们向该函数传递一个数字,并尝试打印一个 name 属性时,没有报错:,打开 noImplicitAny 选项后,如果我们没有显式地声明 a 的类型,TypeScript 将立即标记一个错误:,当 strictNullChecks 选项为 false 时,TypeScript 实际上会忽略 null 和 undefined。这可能会在运行时导致意外错误。,当 strictNullChecks 设置为 true 时,null 和 undefined 有它们自己的类型,如果你将它们分配给一个期望具体值(例如,字符串)的变量,则会得到一个类型错误。,singles.find 并不能保证它一定能找到这首歌 — 但是我们已经编写了下面的代码,好像它肯定能找到一样。,通过将 strictNullChecks 设置为 true, TypeScript 将抛出一个错误,因为在尝试使用它之前,我们没有保证 single 一定存在:,TypeScript 基本上是告诉我们在使用 single 之前要确保它存在。我们需要先检查它是否为 null 或 undefined:,在 TypeScript 中,变量可以从不太精确的类型转移到更精确的类型,这个过程称为类型收窄。,下面是一个简单的例子,展示了当我们使用带有 typeof 的 if 语句时,TypeScript 如何将不太特定的 string | number 缩小到更特定的类型:,另一个例子:下面,我们定义了一个名为 allVehicles 的联合类型,它可以是 Plane 或 Train 类型。,由于 getSpeedRatio 函数处理了多种类型,我们需要一种方法来区分 v 是 Plane 还是 Train 。我们可以通过给这两种类型一个共同的区别属性来做到这一点,它带有一个字符串值:,现在,TypeScript 可以缩小 v 的类型:,TypeScript 完全支持 React 和 JSX。这意味着我们可以将 TypeScript 与三个最常见的 React 框架一起使用:,如果你需要一个更自定义的 React-TypeScript 配置,你可以字节配置 Webpack 和 tsconfig.json。但是大多数情况下,一个框架就可以完成这项工作。,例如,要用 TypeScript 设置 create-react-app,只需运行:,在 src 文件夹中,我们现在可以创建带有 .ts (普通 TypeScript 文件)或 .tsx (带有 React 的 TypeScript 文件)扩展名的文件,并使用 TypeScript 编写我们的组件。然后将其编译成 public 文件夹中的 JavaScript 。,Person 是一个 React 组件,它接受一个 props 对象,其中 name 应该是一个字符串,age 是一个数字。,一般我们更喜欢用 interface 定义 props:,然后我们尝试将组件导入到 App.tsx,如果我们没有提供必要的 props,TypeScript 会报错。,我们可以用尖括号来声明状态变量的类型。如果我们省略了尖括号,TypeScript 会默认推断 cash 是一个数字。因此,如果想让它也为空,我们必须指定:,useRef 返回一个可变对象,该对象在组件的生命周期内都是持久的。我们可以告诉 TypeScript   ref 对象应该指向什么:,

© 版权声明

相关文章