一、基础类型
数据类型 | 关键字 | 描述 |
---|---|---|
任意类型 | any | 声明为 any 的变量可以赋予任意类型的值。 |
数字类型 | number | 双精度 64 位浮点值。它可以用来表示整数和分数。 let binaryLiteral: number = 0b1010; // 二进制 let octalLiteral: number = 0o744; // 八进制 let decLiteral: number = 6; // 十进制 let hexLiteral: number = 0xf00d; // 十六进制 |
字符串类型 | string | 一个字符系列,使用单引号(')或双引号(")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。 let name: string = "Runoob"; let years: number = 5; let words: string = `您好,今年是 ${ name } 发布 ${ years + 1} 周年`; |
布尔类型 | boolean | 表示逻辑值:true 和 false。 let flag: boolean = true; |
数组类型 | 无 | 声明变量为数组。 // 在元素类型后面加上[] let arr: number[] = [1, 2]; // 或者使用数组泛型 let arr: Array<number> = [1, 2]; |
元组 | 无 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。 let x: [string, number]; x = ['Runoob', 1]; // 运行正常 x = [1, 'Runoob']; // 报错 console.log(x[0]); // 输出 Runoob |
枚举 | enum | 枚举类型用于定义数值集合。 enum Color {Red, Green, Blue}; let c: Color = Color.Blue; console.log(c); // 输出 2 |
void | void | 用于标识方法返回值的类型,表示该方法没有返回值。 function hello(): void { alert("Hello Runoob"); } |
null | null | 表示对象值缺失。 |
undefined | undefined | 用于初始化变量为一个未定义的值 |
never | never | never 是其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |
Any
null和undefined
never
二、变量声明
//声明变量的类型及初始值:
var [变量名] : [类型] = 值;
var uname:string = "Runoob";
//声明变量的类型,但没有初始值,变量值会设置为 undefined:
var [变量名] : [类型];
var uname:string;
//声明变量并初始值,但不设置类型,该变量可以是任意类型:
var [变量名] = 值;
var uname = "Runoob";
//声明变量没有设置类型和初始值,类型可以是任意类型,默认初始值为 undefined:
var [变量名];
var uname;
类型断言
类型断言可以用来手动指定一个值的类型,即允许变量从一种类型更改为另一种类型。
语法格式:
<类型>值
或
值 as 类型
实例
var str = '1'
var str2:number = <number> <any> str //str、str2 是 string 类型
console.log(str2)
TypeScript 是怎么确定单个断言是否足够
当 S 类型是 T 类型的子集,或者 T 类型是 S 类型的子集时,S 能被成功断言成 T。这是为了在进行类型断言时提供额外的安全性,完全毫无根据的断言是危险的,如果你想这么做,你可以使用 any。
类型推断
当类型没有给出时,TypeScript 编译器利用类型推断来推断类型。
如果由于缺乏声明而不能推断出类型,那么它的类型被视作默认的动态 any 类型。
var num = 2; // 类型推断为 number
console.log("num 变量的值为 "+num);
num = "12"; // 编译错误
console.log(num);
-
第一行代码声明了变量 num 并=设置初始值为 2。 注意变量声明没有指定类型。因此,程序使用类型推断来确定变量的数据类型,第一次赋值为 2,num 设置为 number 类型。
-
第三行代码,当我们再次为变量设置字符串类型的值时,这时编译会错误。因为变量已经设置为了 number 类型。
一、函数
1. 可选参数和默认参数
在 TypeScript 函数里,如果我们定义了参数,则我们必须传入这些参数,除非将这些参数设置为可选,可选参数使用问号标识 ?。
function buildName(firstName: string, lastName: string) {
return firstName + " " + lastName;
}
let result1 = buildName("Bob"); // 错误,缺少参数
let result2 = buildName("Bob", "Adams", "Sr."); // 错误,参数太多了
let result3 = buildName("Bob", "Adams"); // 正确
可选参数必须跟在必需参数后面。 如果上例我们想让 firstName 是可选的,lastName 必选,那么就要调整它们的位置,把 firstName 放在后面。如果都是可选参数就没关系。
2. 函数重载
重载是方法名字相同,而参数不同,返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
参数类型不同:
function disp(string):void;
function disp(number):void;
参数数量不同:
function disp(n1:number):void;
function disp(x:number,y:number):void;
参数类型顺序不同:
function disp(n1:number,s1:string):void;
function disp(s:string,n:number):void;
如果参数类型不同,则参数类型应设置为 any。
参数数量不同你可以将不同的参数设置为可选。
实例
以下实例定义了参数类型与参数数量不同:
function disp(s1:string):void;
function disp(n1:number,s1:string):void;
function disp(x:any,y?:any):void {
console.log(x);
console.log(y);
}
disp("abc")
disp(1,"xyz");
编译以上代码,得到以下 JavaScript 代码:
function disp(x, y) {
console.log(x);
console.log(y);
}
disp("abc");
disp(1, "xyz");
//输出结果:
abc
undefined
1
xyz
(见笔记)
定义函数重载需要定义重载签名和一个实现签名。
重载签名定义函数的形参和返回类型,没有函数体。一个函数可以有多个重载签名(不可调用)
let suits = ["hearts", "spades", "clubs", "diamonds"];
// 定义重载签名
function greet(person: string): string;
function greet(persons: string[]): string[];
// 定义实现签名
function greet(person: unknown): unknown {
if (typeof person === 'string') {
return `Hello, ${person}!`;
} else if (Array.isArray(person)) {
return person.map(name => `Hello, ${name}!`);
}
throw new Error('Unable to greet');
}
console.log(greet(suits[0]));
console.log(greet(suits));
二、元组
在数组中我们使用括号加竖线的方式限定数组中可以使用多种数据类型,但是这样并不能按顺序限定,较为灵活,此时我们就需要一个类型可以先注类型的同时,还能限定改类型数据在数组中的位置,此时我们就引入了元组,如下我们定义一个元组:
const student : [number, string, boolean] = [10001, "张三", true];
三、联合类型
联合类型(Union Types)可以通过管道(|)将变量设置多种类型,赋值时可以根据设置的类型来赋值。
注意:只能赋值指定的类型,如果赋值其它类型就会报错。
创建联合类型的语法格式如下:
Type1|Type2|Type3
实例
声明一个联合类型:
var val:string|number
val = 12
console.log("数字为 "+ val)
val = "Runoob"
console.log("字符串为 " + val)
如果赋值其它类型就会报错:
var val:string|number
val = true
联合类型数组
我们也可以将数组声明为联合类型:
var arr:number[]|string[];
四、接口
interface interface_name {
}
可索引的类型
与使用接口描述函数类型差不多,我们也可以描述那些能够“通过索引得到”的类型,比如a[10]
或ageMap["daniel"]
。 可索引类型具有一个 索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。 让我们看一个例子:
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
接口继承
接口继承就是说接口可以通过其他接口来扩展自己。
Typescript 允许接口继承多个接口。
继承使用关键字 extends。
单接口继承语法格式:
Child_interface_name extends super_interface_name
多接口继承语法格式:
Child_interface_name extends super_interface1_name, super_interface2_name,…,super_interfaceN_name
继承的各个接口使用逗号 , 分隔。
多继承实例
interface IParent1 {
v1:number
}
interface IParent2 {
v2:number
}
interface Child extends IParent1, IParent2 { }
var Iobj:Child = { v1:12, v2:23}
console.log("value 1: "+Iobj.v1+" value 2: "+Iobj.v2)
五、类和接口
类可以实现接口,使用关键字 implements,并将 interest 字段作为类的属性使用。
以下实例红 AgriLoan 类实现了 ILoan 接口:
interface ILoan {
interest:number
}
class AgriLoan implements ILoan {
interest:number
rebate:number
constructor(interest:number,rebate:number) {
this.interest = interest
this.rebate = rebate
}
}
var obj = new AgriLoan(10,1)
console.log("利润为 : "+obj.interest+",抽成为 : "+obj.rebate )
六、命名空间
命名空间一个最明确的目的就是解决重名问题。
假设这样一种情况,当一个班上有两个名叫小明的学生时,为了明确区分它们,我们在使用名字之外,不得不使用一些额外的信息,比如他们的姓(王小明,李小明),或者他们父母的名字等等。
命名空间定义了标识符的可见范围,一个标识符可在多个名字空间中定义,它在不同名字空间中的含义是互不相干的。这样,在一个新的名字空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其他名字空间中。
TypeScript 中命名空间使用 namespace 来定义,语法格式如下:
namespace SomeNameSpaceName {
export interface ISomeInterfaceName { }
export class SomeClassName { }
}
以上定义了一个命名空间 SomeNameSpaceName,如果我们需要在外部可以调用 SomeNameSpaceName 中的类和接口,则需要在类和接口添加 export 关键字。
要在另外一个命名空间调用语法格式为:
SomeNameSpaceName.SomeClassName;
如果一个命名空间在一个单独的 TypeScript 文件中,则应使用三斜杠 /// 引用它,语法格式如下:
/// <reference path = "SomeFileName.ts" />
嵌套命名空间
命名空间支持嵌套,即你可以将命名空间定义在另外一个命名空间里头。
namespace namespace_name1 {
export namespace namespace_name2 {
export class class_name { }
}
}
成员的访问使用点号 . 来实现