TypeScript学习-数据类型

124 阅读8分钟

数据类型

概念

JavaScript数据类型分为基本类型引用数据类型TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了枚举类型进行使用。

基本类型包括字符串(string)数值(number)布尔值(boolean)对空(null)未定义(undefined)以及**ES6**添加的Symbol类型。

引用数据类型包括数组(Array)对象(Object)函数(Function)

基本类型

布尔值(boolean)

布尔值是最简单的基本数据类型,只存在两个值,truefalse,在编程语言中使用符号boolean表示。

let foo: boolean = true
let bar: boolean = false
console.log(foo) // true
console.log(bar) // false

上面代码中声明了foobar两个变量,通过类型声明,将两个变量的数据类型都设置为boolean,并且赋值,进行编译,查看控制台,输出truefalse两个值。

boolean

判断一个变量是不是布尔值,通过typeof进行判断。

if (typeof foo === "boolean") {
    console.log('foo is a boolean')
} else {
    console.log('foo is not a boolean')
}
// foo is a boolean

上面代码通过typeof判断foo变量的类型是不是等于boolean类型,上面代码输出foo is a boolean,证明所声明的变量foo是一个布尔值。

数字(number)

数字型采用number关键字进行声明,TypeScript里面所有数值都是浮点数,

let foo: number = 1 // 10进制数
let bar: number = 0x0f00 // 16进制数
let baz: number = 0b1010 // 2进制数
let num: number = 0o711 // 8进制数
console.log(foo) // 1
console.log(bar) // 3840
console.log(baz) // 10
console.log(num) // 457

上面代码一共有四个变量,并且每个变量都是number类型,其中foo表示10进制数,bar表示16进制数,baz表示2进制数,num表示8进制数,通过编译命令进行编译该代码,得到下面结果。

number编译结果

在上面代码中,我们将foo值改变,另外赋一个字符串的值给foo,编译失败,提示Type 'string' is not assignable to type 'number',报错提示字符串类型不可装换成数值型。

foo = "1"

编译失败

字符串(string)

字符串是基本数据类型中的一种,表示文本数据,使用关键字string声明类型,使用""或者''表示字符串。

let username: string = "typescript"
console.log(username) // typescript

上面代码声明一个变量username,该变量的类型为string,给变量赋初值为"typescript",然后编译输出为"typescript"

同样的,这里也可以结合ES6的模板字符串,用它来定义多行文本和内嵌表达式。模板字符串使用``表示,并且以${expr}嵌入表达式。

let username: string = `typescript`
let age: number = 10
let description: string = `${username}已经发展将近${age}年了`
console.log(description) // typescript已经发展将近10年了

上面代码声明了三个模板字符串,分别是usernameagedescription,通过模板字符串将他们构建在一起,最后编译输出typescript已经发展将近10年了

typescript

Null和undefined

TypeScript中,可以使用null或者undefined来定义这两个原始的数据类型,和void相似,它们的本身的类型用处不是很大。

下面定义两个变量,分别表示nullundefined

let n: null = null
let u: undefined = undefined

void不同的是,nullundefined是所有类型的子类型,nullundefined声明的变量可以赋值给number类型的变量。

然而,当你指定了--strictNullChecks标记,nullundefined只能赋值给void和它们各自。 这能避免 很多常见的问题。 也许在某处你想传入一个stringnullundefined,你可以使用联合类型string | null | undefined

枚举

enum类型是对JavaScript标准数据类型的一个补充,就像Java等其他语言一样,使用枚举类型可以为一组数值赋予友好的名字。

enum Color {
    Red,
    Green,
    Blue
}
let c: Color = Color.Green

默认情况下,从0开始为元素编号,当然,你也可以手动的指定成员的数值。例如将上面代码改为从2开始编号。

enum Color {
    Red,
    Green = 2,
    Blue
}
let c: Color = Color.Green
console.log(c) // 2

上面代码中,将Green成员指定为2,然后获取到该成员为2

枚举成员赋值

同时也可以给全部的成员手动赋值。

enum Color {
    Red = 1,
    Green = 2,
    Blue = 3
}
let c: Color = Color.Green

枚举类型提供的一个便利是你可以由枚举的值得到它的名字,例如,我们都知道数值为2,但是不能确定它映射到Color里的哪个名字,我们就可以查到相应的名字。

enum Color {
    Red = 1,
    Green = 2,
    Blue = 3
}
let colorName: string = Color[2]
console.log(colorName) // Green

任意值(Any)

有时候,我们会想在为那些在编程阶段还不清楚类型的变量指定一个类型,这些值可能来自于动态的内容,比如来自用户输入或者第三方代码库,这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用any类型来标记这些变量。

let foo: any = 4
foo = "4"
foo = false
console.log(foo) // false

在对现有代码进行改写的时候,Any类型是十分有用的,它允许你在编译时可选择地包含或移除类型检查。 你可能认为Object有相似的作用,就像它在其它语言中那样。但是 Object类型的变量只是允许你给它赋任意值,但是却不能够在它上面调用任意的方法,即便它真的有这些方法。

let foo: any = 4;
foo.ifItExists(); // okay, ifItExists might exist at runtime
console.log(foo.toFixed()); // 4

let prettySure: Object = 4;
prettySure.toFixed(); // Property 'toFixed' does not exist on type 'Object'.

当你只知道一部分数据的类型时,any类型也是有用的。比如,你有一个数组,它包含了不同的类型的数据。

let array: any[] = [1, "2", true]

console.log(array[2]) // true

Never

Never类型表示的是那些永不存在的值的类型。例如,Never总是会抛出异常或者根本就不会有返回值的函数表达式或者箭头函数表达式的返回值类型,变量可能是Never类型,当它们被永不为真的类型所约束时。

Never类型是任何类型的子类型,也可以赋值给任何类型。然而,没有类型是Never的子类型或可以赋值给Never类型(除了Never本身之外)。 即使Any也不可以赋值给Never

// 返回Never的函数必须在无法达到的终点
function error(message: string): never {
    throw new Error(message)
}

// 推断的返回值类型为never
function fail() {
    return error("Something failed")
}

// 返回Never的函数必须在无法达到的终点
function infiniteLoop(): never {
    while (true) {

    }
}

引用数据类型

数组

TypeScriptJavaScript一样可以操作数组元素,有两种方法可以定义数组,第一种是,可以在元素后面跟上[],表示由类型元素组成的数组。

let arrayNumber: number[] = [1, 2, 3]

let arrayString: string[] = ["1", "2"]

上面代码所声明是变量arrayNumber是一个类型为number的数组array,数组内部元素只能是number类型的,而另外一个数组arrayString是定义类型为string的数组,该数组元素只能是字符串类型。

第二种方式就是使用数组泛型,Array<元素类型>

let array: Array<number> = [1, 2, 3]
console.log(array) // [ 1, 2, 3 ]

Array<number>

元组Tuple

元组数据允许表示一个已知元素数量和数据类型的数组,各元素类型可以不必相同,比如,你可以定义一对键值对分别为stringnumber类型元组。

let array: [number, string]
array = [1, "2"]
console.log(array) // [ 1, '2' ]

上面代码中,声明一个元组array,该元组只有两个元素,并且分别是numberstring,如果在赋值的时候,不按照对应的位置进行赋值,那么就会报错。比如下面的代码。

let array: [number, string]
array = [1, 2]
console.log(array) // Type 'string' is not assignable to type 'number'

当我们访问某个元素时,会得到正确的类型。

let array: [number, string]
array = [1, "2"]
if (typeof array[0] === "number") {
    console.log(array[0])
}

if (typeof array[1] === "string") {
    console.log(array[1])
}

上面代码中,通过数组索引访问数组成员,使用typeof类型判断函数,当**typeof array[0] === "number"为真时,就会输出元组第一个元素1,当typeof array[1] === "string"**为真时,输出第二个数组元素'2'。这样就做到了类型判断。

void类型

JavaScript没有空值这个概念,在TypeScript中,可以使用void表示没有任何返回值的函数。

声明一个void类型的变量,你就可以将它赋值为nullundefined

function getName(username: string): void {
    console.log("my name is " + username)
}

let username: string = "typescript"
getName(username)

上面代码中,编写了一个getName函数,并且函数设置有参数usernamestring,并且将该返回值设置为void,通过传参给该函数,最后输出my name is typescript

Object

Object类型称为对象,是引用数据类型,表示非原始数据。

使用Object类型,就可以很好的表示像Object.create这样的API

declare function create(o: object | null): void

create({ prop: 0 }) // OK
create(null) // OK

create(1) // Error
create("string") // Error
create(false) // Error
create(undefined) // Error