把青春献给身后那座辉煌的都市,为了这个美梦我们付出着代价
目录
一,基础类型
二,数组
三,any
四,变量的类型注释
五,函数
5.1 参数类型注解
5.2 返回类型注解
5.3 匿名函数
六,对象类型
可选属性
七,联合类型
7.1 定义联合类型
7.2 使用联合类型
八,类型别名
九,接口
类型别名和接口的区别
十,类型断言
十一,null 和 undefined
非空断言运算符(后缀 !)
十二,枚举
数字枚举
字符串枚举
一,基础类型
TypeScript 有三个非常常用的基础类型:string
、number
和 boolean
string
表示字符串值,如 "Hello, world"
number
代表数字。TypeScript 没有特殊的整数运行时值,因此没有相当于 int
或 float
的值 ,一切都只是 number
boolean
代表 true
和 false
这两个值
注意: String
、Number
和 Boolean
(以大写字母开头)是合法的,但指的是一些很少出现在代码中的特殊内置类型。所以开发中我们一般使用 string
、number
或 boolean
作为类型。
二,数组
数组的第一种写法:
numberArry:number[] =[1,2,3,4,5]
stringArry:string[] =["a","b","c","d"]
booleanArry:boolean[] = [true,false,true]
数组的第二中写法:
numberArry1:Array<number> =[1,2,3,4,5]
stringArry1:Array<string> =["a","b","c","d"]
booleanArry1:Array<boolean> = [true,false,true]
注意,[number]
是另一回事,不是数组
三,any
当一个值的类型为 any
时,你可以访问它的任何属性,像函数一样调用它,将它分配给任何类型的值,或者几乎任何其他东西这在语法上是合法的
obj:any = {
a:1,
b:"11"
}
注意:ArkTs已经不支持any
四,变量的类型注释
当使用 const
、var
或 let
声明变量时,可以选择添加类型注释以显式指定变量的类型,也可以不用注释,因为TS会自动推断代码中的类型。
test(){
let a:number = 1
let b =2
const c:string = "3"
const d="4"
}
五,函数
5.1 参数类型注解
声明函数时,可以在每个参数后面加上类型注解,声明函数接受哪些类型的参数。参数类型注释在参数名称之后:
function test(name:string){
console.log(name)
}
当参数具有类型注释时,将检查该函数的参数:
5.2 返回类型注解
可以添加返回类型注释。返回类型注释出现在参数列表之后:
function test(name:string):number{
console.log(name)
return 888
}
与变量类型注解非常相似,通常不需要返回类型注解,因为 TypeScript 会根据其 return
语句推断函数的返回类型。
返回Promise的函数:
async function test(name:string):Promise<number> {
console.log(name)
return 888
}
或者
function test1(name:string):Promise<number> {
console.log(name)
return new Promise((resolve, reject) => {
if(name){
resolve(999)
}else {
reject(888)
}
})
}
5.3 匿名函数
匿名函数与函数声明有点不同。当一个函数出现在 TypeScript 可以确定如何调用它的地方时,该函数的参数会自动被赋予类型。
const names = ["Alice", "Bob", "Eve"];
names.forEach(function (s) {
console.log(s.toUpperCase());
});
即使参数 s
没有类型注释,TypeScript 还是使用 forEach
函数的类型以及推断的数组类型来确定 s
将具有的类型。这个过程称为上下文类型,因为函数发生的上下文告知它应该具有什么类型。
或者
export default class TsTest {
numberArry:number[] =[1,2,3,4,5]
method(){
this.numberArry.forEach((item,index)=>{
})
}
}
六,对象类型
要定义对象类型,我们只需列出其属性及其类型。
function duixiang(obj:{x:number,y:number}){
console.log(obj.x+obj.y+"")
}
可选属性
对象类型还可以指定它们的部分或全部属性是可选的。为此,请在属性名称后添加 ?
:
function duixiang(obj:{x:number,y?:number}){
console.log(obj.x+obj.y+"")
}
method(){
duixiang({x:1})
duixiang({x:1,y:2})
}
七,联合类型
7.1 定义联合类型
联合类型是由两种或多种其他类型组成的类型,表示可能是这些类型中的任何一种的值。我们将这些类型中的每一种都称为联合的成员。
export default class TsTest {
name:string | number
union(){
this.name = 1 //ok
this.name = "11" //ok
this.name= false //Type 'boolean' is not assignable to type 'string | number'. <ArkTSCheck>
}
}
7.2 使用联合类型
TypeScript 只有在对联合的每个成员都有效的情况下才允许操作。例如,如果你有联合 string | number
,则不能使用仅在 string
上可用的方法:
union(){
this.name.toUpperCase()//Property 'toUpperCase' does not exist on type 'string | number'. Property 'toUpperCase' does not exist on type 'number'
}
解决方案是用代码缩小联合,就像在没有类型注释的 JavaScript 中一样。当 TypeScript 可以根据代码的结构为某个值推断出更具体的类型时,就会发生缩小。
union(){
if(typeof this.name === "string"){
console.log(this.name.toUpperCase())//ok
}else {
this.name++ //ok
}
}
八,类型别名
我们一直通过直接在类型注释中编写对象类型和联合类型来使用它们。这很方便,但通常希望多次使用同一个类型并用一个名称引用它。
type YuanZhen = {
name:string;
age:number;
}
export default class TsTest {
union(yuan:YuanZhen){
yuan.name="袁震"
yuan.age=30
}
}
可以使用类型别名来为任何类型命名,而不仅仅是对象类型。例如,类型别名可以命名联合类型:
type Yuan= number | string | boolean
九,接口
接口声明是命名对象类型的另一种方式:
interface Point {
x: number;
y: number;
}
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 100, y: 100 });
就像我们在上面使用类型别名时一样,该示例就像我们使用匿名对象类型一样工作。TypeScript 只关心我们传递给 printCoord
的值的结构 - 它只关心它是否具有预期的属性。只关心类型的结构和功能是我们称 TypeScript 为结构类型类型系统的原因。
类型别名和接口的区别
类型别名和接口非常相似,在很多情况下你可以在它们之间自由选择。interface
的几乎所有功能都在 type
中可用,主要区别在于无法重新打开类型以添加新属性,而接口始终可扩展。
扩展接口:
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;
通过交叉扩展类型:
type Animal = {
name: string;
}
type Bear = Animal & {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;
十,类型断言
有时你会得到关于 TypeScript 无法知道的值类型的信息。
例如,如果你使用的是 document.getElementById
,TypeScript 只知道这将返回某种 HTMLElement
,但你可能知道你的页面将始终具有具有给定 ID 的 HTMLCanvasElement
。
在这种情况下,你可以使用类型断言来指定更具体的类型:
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
与类型注释一样,类型断言被编译器删除,不会影响代码的运行时行为。
const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");
十一,null
和 undefined
JavaScript 有两个基础值用于表示值不存在或未初始化的值:null
和 undefined
。
当值为 null
或 undefined
时,需要在对该值使用方法或属性之前测试这些值。就像在使用可选属性之前检查 undefined
一样,可以使用缩小来检查可能是 null
的值:
function doSomething(x: string | null) {
if (x === null) {
// do nothing
} else {
console.log("Hello, " + x.toUpperCase());
}
}
非空断言运算符(后缀 !
)
TypeScript 还具有一种特殊的语法,可以在不进行任何显式检查的情况下从类型中删除 null
和 undefined
。在任何表达式之后写 !
实际上是一个类型断言,该值不是 null
或 undefined
:
function liveDangerously(x?: number | null) {
// No error
console.log(x!.toFixed());
}
就像其他类型断言一样,这不会改变代码的运行时行为,所以当你知道值不能是 null
或 undefined
时,只使用 !
很重要。
十二,枚举
枚举允许开发者定义一组命名常量。使用枚举可以更轻松地记录意图,或创建一组不同的案例。TypeScript 提供基于数字和基于字符串的枚举。
数字枚举
可以使用 enum
关键字定义枚举。
enum Direction {
Up = 1,
Down,
Left,
Right,
}
上面,我们有一个数字枚举,其中 Up
用 1
初始化。从那时起,以下所有成员都会自动递增。换句话说,Direction.Up
的值为 1
,Down
的值为 2
,Left
的值为 3
,Right
的值为 4
。
或者:
enum Direction {
Up,
Down,
Left,
Right,
}
在这里,Up
的值为 0
,Down
的值为 1
,以此类推。这种自动递增行为对于我们可能不关心成员值本身但要注意每个值与同一个中的其他值不同的情况很有用枚举。
字符串枚举
在字符串枚举中,每个成员都必须使用字符串字面或另一个字符串枚举成员进行常量初始化。
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
虽然字符串枚举没有自动递增行为,但字符串枚举的好处是它们 “serialize” 很好。换句话说,如果你正在调试并且必须读取数字枚举的运行时值,则该值通常是不透明的 - 它本身并没有传达任何有用的含义
字符串枚举允许你在代码运行时提供有意义且可读的值,而与枚举成员本身的名称无关。