当前位置: 首页 > Web前端 > JavaScript

TypeScript的常见类型(下)_0

时间:2023-03-27 01:20:53 JavaScript

TypeScript的官方文档已经更新了,但我能找到的中文文档还是旧版本。因此,对一些新增和修改的章节进行了翻译和整理。本译文整理自TypeScriptHandbook中的“EverydayTypes”一章。本文并没有严格按照原文翻译,部分内容也做了说明和补充。常见类型(EverydayTypes)在本章中,我们将讲解JavaScript中最常见的一些类型及其对应的描述方法。请注意,本章并不详尽,后续章节将解释更多命名和使用类型的方法。类型可以出现在很多地方,而不仅仅是类型注释。我们不仅要学习类型本身,还要学习它们用于生成新结构的位置。让我们首先回顾一下最基本和最常见的类型,它们是构建更复杂类型的基础。原始类型:字符串、数字和布尔值(Theprimitives)JavaScript有三种非常常用的原始类型:字符串、数字和布尔值,每种类型在TypeScript中都有对应的类型。它们的名称与JavaScript中的typeof运算符的名称相同。string表示一个字符串,比如“Hello,world”number表示一个数字,比如42,JavaScript中没有int和float,所有的数字都是类型numberboolean表示一个布尔值,其实只有两个值:true和false类型名称String、Number和Boolean(大写)也是合法的,但它们是一些非常罕见的特殊内置类型。所以类型总是使用string、number或boolean。数组(Array)声明一个数组类型,如[1,2,3],需要使用语法number[]。此语法适用于任何类型(例如,string[]表示字符串数组)。你可能还会看到这样写Array,也是一样的。我们将在泛型章节中向您介绍T语法。注意[number]和number[]有不同的含义,参考元组章节anyTypeScript有一个特殊的类型any,当你不想让一个值导致类型检查错误时,可以将它设置为any。当一个值是任何类型时,你可以得到它的任何属性(也会被转换成任何类型),或者像函数一样调用它,将它赋值给任何类型的值,或者赋值给任何类型的值它,或任何其他语法正确的操作:letobj:any={x:0};//以下代码行都不会抛出编译器错误。//使用`any`会禁用所有进一步的类型检查,并且假定//你比TypeScript.obj.foo();obj();obj.bar=100;obj="hello";constn:number=obj;更了解环境当你不想写一个Long类型的代码,只想让TypeScript知道一个特定的代码是没有问题的,任何类型都非常有用。noImplicitAny如果您不指定类型并且TypeScript无法从上下文推断其类型,则编译器将默认为any。如果你一直想避免这种情况,毕竟TypeScript不会对any做类型检查,你可以开启编译项noImplicitAny,隐式推断为any时TypeScript会报错。变量类型注解(TypeAnnotationsonVariables)当你使用const、var或let声明一个变量时,你可以选择添加一个类型注解来显式指定变量的类型:letmyName:string="Alice";TypeScript不使用“左边类型声明”的形式,比如intx=0;类型注释通常跟在要声明的类型的内容之后。但大多数时候,这是没有必要的。因为TypeScript会自动推断类型。例如,可以根据初始值推断变量的类型://Notypeannotationneeded--'myName'inferredastype'string'letmyName="Alice";大多数时候,您不需要学习推理规则。如果您刚刚开始,请尝试使用尽可能少的类型注释。您可能会惊讶于TypeScript只需要很少的东西就可以完全理解正在发生的事情。函数(Function)函数是JavaScript中传递数据的主要方法。TypeScript允许您指定函数的输入和输出值的类型。参数类型注解(ParameterTypeAnnotations)当你声明一个函数时,你可以在每个参数后面加上一个类型注解来声明这个函数可以接受什么类型的参数。参数类型注解跟在参数名称后面://参数类型注解functiongreet(name:string){console.log("Hello,"+name.toUpperCase()+"!!");}当参数有类型时annotation,TypeScript将检查函数的实际参数://如果执行将是运行时错误!greet(42);//'number'类型的参数不可分配给'string'类型的参数。即使你没有For类型注解,TypeScript仍然会检查传入参数的数量是否正确返回类型注解(ReturnTypeAnnotations)你也可以为返回值添加类型注解。返回值的类型注解跟在参数列表后面:functiongetFavoriteNumber():number{return26;}和变量类型注解一样,你并不总是需要添加返回值类型注解,TypeScript会根据它来推断函数return语句返回类型。像这个例子,类型注解写的和不写的是一样的,但是有些代码库会显式指定返回值的类型,可能是因为需要写文档,或者是为了防止误修改,或者只是个人喜好。匿名函数(AnonymousFunctions)匿名函数与函数声明有点不同。当TypeScript知道匿名函数将如何被调用时,匿名函数的参数将被自动分配类型。这是一个示例://这里没有类型注释,但TypeScript可以发现错误constnames=["Alice","Bob","Eve"];//functionnames.forEach(function(s){console.log(s.toUppercase());//属性'toUppercase'在类型'string'上不存在。你是说'toUpperCase'吗?});//上下文类型也适用于箭头函数names.forEach((s)=>{console.log(s.toUppercase());//属性'toUppercase'在类型'string'上不存在。你是说'toUpperCase'?});虽然参数s没有加类型注解,但是TypeScript根据forEach函数的类型,以及传入的数组类型,最终推导出s的类型。这个过程被称为上下文类型化,因为它是从函数出现的上下文中推断出它应该具有的类型。和推理规则一样,你不需要去了解它是如何发生的,只需要知道它确实存在并且帮你省去一些你不需要的注解即可。我们稍后会看到更多这样的例子,以及值出现的上下文如何影响它的类型。对象类型(ObjectTypes)除了原始类型,最常见的类型是对象类型。要定义一个对象类型,我们只需列出它的属性和它们对应的类型。例如://参数的类型注解是一个对象typefunctionprintCoord(pt:{x:number;y:number}){console.log("坐标的x值为"+pt.x);console.log("坐标的y值为"+pt.y);}printCoord({x:3,y:7});这里,我们给参数添加了一个类型,它有两个属性,x和y,两个都是number类型。您可以使用,或;分隔属性,最后一个属性有或没有定界符。每个属性对应的type是可选的,如果不指定,默认使用any。可选属性(OptionalProperties)对象类型可以指定部分甚至所有属性为可选,你只需要添加一个?在属性名称之后:functionprintName(obj:{first:string;last?:string}){//...}//BothOKprintName({first:"Bob"});printName({first:"Alice",last:"Alisson"});在JavaScript中,如果你得到一个不存在的属性,你将得到一个未定义的错误而不是运行时错误。因此,当你获取一个可选属性时,在使用它之前需要检查它是否是undefined。functionprintName(obj:{first:string;last?:string}){//错误-如果没有提供'obj.last'可能会崩溃!console.log(obj.last.toUpperCase());//对象可能是“未定义的”。if(obj.last!==undefined){//OKconsole.log(obj.last.toUpperCase());}//使用现代JavaScript语法的安全替代方案:console.log(obj.last?.toUpperCase());}联合类型(UnionTypes)TypeScript类型系统允许您使用一系列运算符基于现有类型。现在我们知道如何编写一些基本类型,是时候将它们放在一起了。定义联合类型(DefiningaUnionType)组合类型的第一种方法是使用联合类型。联合类型是由两种或多种类型组成的类型,表示值可能是这些类型中的任何一种。这些类型中的每一个都是联合类型的成员。让我们写一个函数来处理字符串或数字:functionprintId(id:number|string){console.log("YourIDis:"+id);}//OKprintId(101);//OKprintId("202");//ErrorprintId({myID:22342});//类型的参数'{myID:number;}'不可分配给'string|类型的参数number'.//输入'{myID:number;}'不可分配给类型'number'。使用联合类型很容易提供一个符合联合类型的值,你只需要提供一个符合任何联合成员类型的值。那么一旦你有了一个联合类型的值,你如何使用它呢?TypeScript要求你做的事情必须对联盟的每个成员都有效。例如,如果您有联合类型字符串|number,你不能使用只存在于字符串上的方法:functionprintId(id:number|string){console.log(id.toUpperCase());//属性“toUpperCase”在类型“string”上不存在|数字'。//属性'toUpperCase'在类型'number'上不存在。}解决方案是使用代码缩小联合类型,就像在没有类型注释的JavaScript中一样。当TypeScript可以根据代码结构推断出更具体的类型时,就会发生类型缩小。例如,TypeScript知道对字符串类型的值使用typeof将返回字符串“string”:functionprintId(id:number|string){if(typeofid==="string"){//在这个分支中,id是'string'类型console.log(id.toUpperCase());}else{//这里,id的类型是'number'console.log(id);}}另一个例子,使用函数,例如Array.isArray:functionwelcomePeople(x:string[]|string){if(Array.isArray(x)){//Here:'x'is'string[]'console.log("你好,"+x.join("and"));}else{//这里:'x'是'string'console.log("欢迎孤独的旅人"+x);}}请注意,在else分支中,我们不需要做任何特殊的事情,如果x不是string[],那么它必须是string。有时候,如果联合类型的每个成员都有一个属性,比如数字和字符串都有一个slice方法,可以直接使用这个属性不需要缩小://Returntypeisinferredasnumber[]|stringfunctiongetFirstThree(x:number[]|string){returnx.slice(0,3);}你可能想知道为什么Union类型只能使用这些类型属性的交集,我们举个例子,现在有两个rooms,一个房间里全是8英尺高的戴帽子的人,另一个房间里全是讲西班牙语的戴帽子的人,合并两个房间后,我们唯一知道的是每个人都戴着帽子.TypeScript系列TypeScript系列文章由官方文档翻译、重点难点解析、实战技巧三部分组成,内容涵盖入门、进阶、实战。旨在为您提供系统的TS学习教程。整个系列预计约有40篇文章。点此浏览全系列文章,建议顺便收藏本站。微信:“mqyqingfeng”,加我到世优唯一的读者群。如有错误或不准确的地方,请务必指正,万分感谢。如果你喜欢或者有启发,欢迎star,这也是对作者的鼓励。