TypeScript 允许我们使用 any 关键字来描述不确定的类型,编译器会自动忽略对该类型的校验:
let notSure: any = 4;
notSure = 'maybe a string instead';
notSure = false; // okay, definitely a boolean与 Object 类型相比,
TypeScript 为我们提供了 number, string, boolean, 等原始类型。跟 JavaScript 一样,TypeScript 所有的数都是浮点数类型,使用 number 关键字描述:
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;如果我们在代码中希望显式区分 int, float 等具体的数值类型,那么可以使用 type 来建立别名:
type int = number;
type float = number;布尔类型的值使用 boolean 关键字描述,包含 true/false 两个值:
let isDone: boolean = false;所有的字符串类型使用 string 关键字描述,包括双引号、单引号以及模板字符串方式声明的字符串对象:
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.`;值得一提的是,就像 Java 中 Long 与 long 的区别,TypeScript 会将 Number, String, Boolean 当做包含特定属性与方法的 Object 类型进行处理,我们应该尽量避免使用复合类似以避免意外地操作:
/* WRONG */
function reverse(s: String): String;
/* OK */
function reverse(s: string): string;类似于 Java 或者 C# 语言中的枚举类型,我们能够使用 enum 关键字来创建预定义好的常量集合:
enum StoryType {
Video,
Article,
Tutorial
}
let st: StoryType = StoryType.Article;值得一提的是,枚举类型被转化为 ES5 代码后,会使用数字来内置表示:
var StoryType;
(function(StoryType) {
StoryType[(StoryType['Video'] = 0)] = 'Video';
StoryType[(StoryType['Article'] = 1)] = 'Article';
StoryType[(StoryType['Tutorial'] = 2)] = 'Tutorial';
})(StoryType || (StoryType = {}));
var st = StoryType.Article;我们同样可以指定枚举值对应的数值:
enum StoryType {Video = 10, Article = 20, Tutorial=30}从 Typescript 2.4 开始,支持了枚举类型使用字符串做为 value:
enum Colors {
Red = 'RED',
Green = 'GREEN',
Blue = 'BLUE'
}在 TypeScript 中,我们能够创建 Typed Arrays 或者 Generic Arrays,Typed Arrays 的创建方式如下:
const tags: string[] = ['javascript', 'programming'];
tags.push('typescript');
tags.forEach(function(tag) {
console.log(`Tag ${tag}`);
});Generic Arrays 的创建方式如下:
let storyLikedBy: Array<number> = [1, 2, 3];我们也可以通过 interface 关键字来自定义数组类型:
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ['Bob', 'Fred'];
let myStr: string = myArray[0];多维数组的声明与初始化方式如下:
class Something {
private things: Thing[][];
constructor() {
things = [];
for (var i: number = 0; i < 10; i++) {
this.things[i] = [];
for (var j: number = 0; j < 10; j++) {
this.things[i][j] = new Thing();
}
}
}
}从 2.7 版本开始,我们可以更精确的描述每一项的类型与数组总长度:
interface Data extends Array<number> {
0: number;
1: number;
length: 2;
}TypeScript 同时提供了 Tuple 元组类型,允许返回包含不同的已知类型的数组:
let storyTitles = [
'Learning TypeScript',
'Getting started with TypeScript',
'Building your first app with TypeScript'
];
let titlesAndLengths: [string, number][] = storyTitles.map(function(title) {
let tuple: [string, number] = [title, title.length];
return tuple;
});元组类型也可以通过 interface 接口方式声明:
interface KeyValuePair extends Array<number | string> {
0: string;
1: number;
}TypeScript 提供了 null, undefined, never, void 这几种空类型,它们都是其他类型的子类型,因为任何有类型的值都有可能是空(也就是执行期间可能没有值)。nerver 用于处理函数的异常流程,譬如永远不会返回值或者抛出异常:
function fail(message: string): never {
throw new Error(message);
}never 类型的典型应用场景,就是处理函数中可能的不可达代码,譬如在调用上述的 fail 函数时,若其为非 never 类型,则会抛出不是所有的代码路径都返回值的异常:
function foo(x: string | number): boolean {
if (typeof x === 'string') {
return true;
} else if (typeof x === 'number') {
return false;
}
return fail('Unexhaustive!');
}TypeScript 3.0 引入了一种名为 unknown 的新类型。与 any 一样,可以把任意值赋给 unknown。不过,与 any 不同的是,如果没有使用类型断言,则几乎没有可赋的值。你也不能访问 unknown 的任何属性,或者调用 / 构建它们。
let foo: unknown = 10;
// 因为 `foo` 是 `unknown` 类型, 所以这些地方会出错。
foo.y.prop;
foo.z.prop;
foo();
new foo();
upperCase(foo);
foo`hello world!`;
function upperCase(x: string) {
return x.toUpperCase();
}这个时候,我们可以执行强制检查,或者使用类型断言。
let foo: unknown = 10;
function hasXYZ(obj: any): obj is { x: any; y: any; z: any } {
return (
!!obj && typeof obj === 'object' && 'x' in obj && 'y' in obj && 'z' in obj
);
}
// 使用用户定义的类型检查...
if (hasXYZ(foo)) {
// ... 现在可以访问它的属性。
foo.x.prop;
foo.y.prop;
foo.z.prop;
}
// 通过使用类型断言,我们告诉 TypeScript,我们知道自己在做什么。
upperCase(foo as string);
function upperCase(x: string) {
return x.toUpperCase();
}