在工作中我们经常用到基础类型,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
类型是无用的,因为你只能用null
和 undefined
类型进行赋值(需要打开 --strictNullChecks
配置):
let unusable: void = undefined;
// OK if `--strictNullChecks` is not given
unusable = null
Null and Undefined
null
和 undefined
类型的值其实用处也不大, 在开启 --strictNullChecks
的前提下,只能赋值给unknown
和 any
和他们各自的类型, 其中 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
, null
和 undefined
, 但是一般情况不会用到:
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等作为类型注解, 而是用小写的方式,尽管它们效果相同