TypeScript - Basic Type (基础类型)

286 阅读5分钟

在工作中我们经常用到基础类型,typescript 提供了和 js 一样的基本类型,比如 boolean, string, number, null 等, 并且额外提供了一些有用的辅助类型,比如枚举 enum

typescript中, 类型注解用 变量名: 类型 方式表示。

Boolean

布尔类型是最简单的类型, 取值为 true/false 。 和js一样, 都用 boolean 表示

let isDone: boolean = false;

Number

数字类型用 number 表示, 大数字用 bigint 表示。 另外可以用 0x, 0b 来表示十六和二进制。

let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
let big: bigint = 100n;

String

字符串可以用双引号和单引号,类型为 string

let color: string = "blue";
color = "red";

可以使用类似ES6的模版字符串

let fullName: string = `Bob Bobbington`;
let age: number = 37;
let sentence: string = `Hello, my name is ${fullName}.

I'll be ${age + 1} years old next month.`;

Array

数组类型有两种方式表示, 第一种是数组元素类型紧跟 [] 表示

let list: number[] = [1, 2, 3];

第二种方式是用数组泛型的方式 Array<elemType>

let list: Array<number> = [1, 2, 3];

Tuple

当我们需要表示固定数量的不同类型元素的数组时候,就需要用到元组:

// Declare a tuple type
let x: [string, number];
// Initialize it
x = ["hello", 10]; // OK
// Initialize it incorrectly
x = [10, "hello"]; // Error

当通过访问固定元素时,ts 会自动推断其类型:

// OK
console.log(x[0].substring(1));

console.log(x[1].substring(1)); //Error

访问索引外的元素和赋值也会报错:

console.log(x[5].toString()); // Error
x[3] = "world"; // Error

Enum

枚举类型是提供一系列的变量来表示数据集的类型, 用 enum 表示:

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

枚举元素默认是从0开始,可以通过设置改变默认值:

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

同样地,可以手动设置枚举元素的所有值:

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

可以用过数值获取对应的枚举名:

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

Unknown

当我们想要表述一个不能确定的类型或者有意接受API返回的所有可能的类型,这时可以用 unknown 类型表示:

let notSure: unknown = 4;
notSure = "maybe a string instead";

// OK, definitely a boolean
notSure = false;

不能赋值给具体类型的变量:

let maybe: unknown

// ok
let maybe1: unknown = maybe
let maybe2: any = maybe1

// error
const name: string = maybe

可以通过比较、typeof 等类型守卫方式来解决:

if (maybe === true) {
  // TypeScript knows that maybe is a boolean now
  const aBoolean: boolean = maybe;
  // So, it cannot be a string
  const aString: string = maybe;
// Type 'boolean' is not assignable to type 'string'.
}

if (typeof maybe === "string") {
  // TypeScript knows that maybe is a string
  const aString: string = maybe;
  // So, it cannot be a boolean
  const aBoolean: boolean = maybe;
// Type 'string' is not assignable to type 'boolean'.
}

Any

在某些情况,并非所有类型信息都是可用的否则他的类型声明将会耗费很大精力。这在不用typescript 编写的代码或者第三方库经常发生。所以,我们选择退出类型检查,可以用 any 表示这些值:

declare function getValue(key: string): any;
// OK, return value of 'getValue' is not checked
const str: string = getValue("myString");

unknown 类型不同,any 类型的变量可以访问任何属性和函数,尽管他们可能不存在,因为 typescrpt 不会检查:

let looselyTyped: any = 4;
// OK, ifItExists might exist at runtime
looselyTyped.ifItExists();
// OK, toFixed exists (but the compiler doesn't check)
looselyTyped.toFixed();

let strictlyTyped: unknown = 4;
strictlyTyped.toFixed(); // Error, Object is of type 'unknown'.

any 类型会在对象访问中传递:

let looselyTyped: any = {};
let d = looselyTyped.a.b.c.d;
//  ^ = let d: any

使用any类型会让我们丢失typescript特性--类型安全,我们应该尽量避免使用

Void

void 有点和 any 类型互斥, 表示不是任何类型。经常会在函数没有返回值时使用:

function warnUser(): void {
  console.log("This is my warning message");
}

定义一个变量为void 类型是无用的,因为你只能用nullundefined 类型进行赋值(需要打开 --strictNullChecks 配置):

let unusable: void = undefined;
// OK if `--strictNullChecks` is not given
unusable = null

Null and Undefined

nullundefined 类型的值其实用处也不大, 在开启 --strictNullChecks的前提下,只能赋值给unknownany 和他们各自的类型, 其中 undefined 赋值给 void 是个例外。否则,它们可以赋值给任何类型:

// Not much else we can assign to these variables!
let u: undefined = undefined;
let n: null = null;

let maybe: unknown = undefined

// strictNullChecks = false
let num:number = undefined

Never

never 类型表示一个总会抛出异常的函数或者死循环的函数,因为它们永远不可能返回值。例外, never 类型不能赋值给任何类型, 其他任何类型也不能赋值给它:

// Function returning never must not have a reachable end point
function error(message: string): never {
  throw new Error(message);
}

// Inferred return type is never
function fail() {
  return error("Something failed");
}

// Function returning never must not have a reachable end point
function infiniteLoop(): never {
  while (true) {}
}

Object

object 类型表示所有非原始类型, 即不是 boolean, number, string, bigint, symbol, nullundefined, 但是一般情况不会用到:

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

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

create(42);
// Argument of type '42' is not assignable to parameter of type 'object | null'.
create("string");
// Argument of type '"string"' is not assignable to parameter of type 'object | null'.
create(false);
// Argument of type 'false' is not assignable to parameter of type 'object | null'.
create(undefined);
// Argument of type 'undefined' is not assignable to parameter of type 'object | null'.

Type assertions

在某些情况,你知道某个值的类型比当前类型更加具体时, 你需要用到类型断言。 类型断言时一种告诉编译器“trust me, I know what I’m doing.”的感觉, 也类似于其他静态语言的类型转换,但是它不执行任何数据检查和转换。另外它只是在编译阶段有效,对运行是没影响的。

类型断言有两种方式,第一钟是 as 语法:

let value: unknown = 'hello'

let len: number = (value as string).length

另一种使用 angle-bracket 语法:

let value: unknown = 'hello'

let len: number = (<string>value).length

其中第一方式优于第二种方式, 并且在JSX使用时,只有用 as 语法

不应该用String, Number等作为类型注解, 而是用小写的方式,尽管它们效果相同