TypeScript 基础类型
数据类型 | 关键字 | 描述 |
---|---|---|
任意类型 | any | 声明为 any 的变量可以赋予任意类型的值 |
数字类型 | number | 双精度 64 位浮点值。它可以用来表示整数和分数 |
字符串类型 | string | 使用单引号(')或双引号(")来表示字符串类型 |
布尔类型 | boolean | 表示逻辑值:true 和 false |
数组类型 | 无 | 声明变量为数组 |
元组Tuple | 无 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同 |
枚举 | enum | 枚举类型用于定义数值集合 |
void | void | 标识方法返回值的类型,表示该方法没有返回值 |
null | null | 表示对象值缺失 |
undefined | undefined | 用于初始化变量为一个未定义的值 |
never | never | 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |
************** 常用写法 **************
//可以用 | 来支持多种类型
let arr1: (number | string)[] = [1, 'a', 3, 'b'];
let x: number | null | undefined;
let decLiteral: number = 6; // 十进制
let arr:Array<number> =[1,2,3] === let arr:number[]=[1,2,3]
const inputValue = ref<(string | number)[]>([0, 0]);
type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback<T> = (data: T) => void;
type Pair<T> = [T, T];
type Coordinates = Pair<number>;
type Tree<T> = T | { left: Tree<T>, right: Tree<T> };
interface SeletI {
label: string;
value: string | number;
}
const unitList1 = ref<SeletI[]>([]);
const unitList2 = ref([] as SeletI[]);
interface Cat {
name?:string; //?表示可以不用
run():void;
}
interface RunOptions {
program:string;
commandline:string[]|string|(()=>string);
}
interface IPerson {
firstName:string,
lastName:string,
sayHi: ()=>string
}
interface namelist {
[index:number]:string
}
//接口中我们可以将数组的索引值和元素设置为不同类型,索引值可以是数字或字符串。
interface namelist {
[index:number]:string
}
// 类型一致,正确
var list2:namelist = ["Google","Runoob","Taobao"]
//数组
let arr: number[] = [1, 2];// 在元素类型后面加上[]
let arr: Array<number> = [1, 2];// 或者使用数组泛型
//元组
let x: [string, number];
x = ['Runoob', 1]; // 运行正常
//枚举
enum Color {Red, Green, Blue};
let c: Color = Color.Blue; // console.log(c); 输出 2
//void
function hello(): void {
alert("Hello Runoob");
}
type 类型别名
// 改造前:
let arr1: (number | string)[] = [1, 'a', 3, 'b'];
let arr2: (number | string)[] = [2, 'c', 4, 'd'];
// 改造后:
type CustomArray = (number | string)[];
let arr1: CustomArray = [1, 'a', 3, 'b'];
let arr2: CustomArray = [2, 'c', 4, 'd'];
const getValue = () => { return 0 }
enum List {
A = getValue(), //A 的值是被计算出来的。某个属性的值是计算出来的,那么它后面一位的成员必须要初始化值
B = 2, // 此处必须要初始化值,不然编译不通过
C
}
console.log(List.A) // 0
console.log(List.B) // 2
console.log(List.C) // 3
enum类型是对JavaScript标准数据类型的一个补充(使用枚举类型可以为一组数值赋予友好的名字 )
enum Language { //枚举名称为大写的单数形式
English, //枚举中的键也为大写
Spanish,
Russian
}
console.log(Language);
//ts自动推导出来的Language如下
{
'0': 'English',
'1': 'Spanish',
'2': 'Russian',
English: 0,
Spanish: 1,
Russian: 2
}
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
//默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值。
//例如,我们将上面的例子改成从 1开始编号:
enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green;
//或者,全部都采用手动赋值:
enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;
//枚举类型提供的一个便利是你可以由枚举的值得到它的名字。
//例如,我们知道数值为2,但是不确定它映射到Color里的哪个名字,我们可以查找相应的名字:
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2]; //console.log(colorName); =>Green'因为上面代码里它的值是2
变量声明
//变量名称可含 数字、字母、 _ 、 $ 不能包含其他特殊字符,包括空格。不能以数字开头。
//var [变量名] : [类型] = 值;
var uname:string = "Runoob";
//var [变量名] : [类型];//声明变量的类型,但没有初始值,变量值会设置为 undefined:
var uname:string;
//var [变量名] = 值;//声明变量并初始值,但不设置类型,该变量可以是任意类型:
var uname = "Runoob";
类型断言(Type Assertion)
- 联合类型可以被断言为其中一个类型
- 父类可断言为更加具体的子类
- 任何类型都可以被断言为any
- any可以被断言为任何类型
<类型>值 或者 值 as 类型
let value: any = 'hello world';
//类型断言
console.log((<string>value).length);
console.log((value as string).length);
//上面的类型断言的写法和下面类型断言的写法完全等价
// 类型断言
(value as string[]).push('test');
(<string[]>value).splice(0,1);
//只能访问联合属性中共有的属性和方法——name。
//如果在不确定类型的时候就想访问一个类型确定的属性和方法,就需要【断言】:
interface Cat {
name:string;
run():void;
}
interface Fish {
name:string;
swim():void;
}
function getName(animal:Cat|Fish):string{
return animal.name;
}
//使用断言 可调用该类型的方法
function isFish(animal:Cat|Fish):boolean{
return (typeof (animal as Fish).swim) === "function";
}
type 作为类型别名使用
//示例1 提取类型
type PlusType = (x:number,y:number) => number;
function sum(x:number,y:number):number =>{ return x+y; }
const sum2: PlusType = sum;
//示例2
type NameResolver = ( ) => string;
type NameOrResolver = string | NameResolver;
function getName( n:NameOrResolver ){
if( typeof n === 'string' ){
return n.length;
}else{
return n().toString.length;
}
}
function getLength( input : string | nmuber ) :number{
const str = input as string;// 将str断言为 string
if( str.length ){
return str.length
}else{
const num = input as number;
return num.toSring().length;
}
}
function getLength( input : string | nmuber ) :number{
if{(<string>input.length){
return input.length;
}else{
return input.toString().length;
}
}
类
class Car {
// 字段
engine:string;
// 构造函数
constructor(engine:string) { this.engine = engine }
// 方法
disp():void { console.log("发动机为 : "+this.engine) }
}
// 创建一个对象
var obj = new Car("XXSY1")
// 访问字段
console.log("读取发动机型号 : "+obj.engine)
// 访问方法
obj.disp()
解析为
var Car = /** @class */ (function () {
// 构造函数
function Car(engine) {
this.engine = engine;
}
// 方法
Car.prototype.disp = function () {
console.log("发动机为 : " + this.engine);
};
return Car;
}());
类继承
class Shape {
Area:number
constructor(a:number) { this.Area = a }
}
class Circle extends Shape {
disp():void { console.log("圆的面积: "+this.Area) }
}
var obj = new Circle(223);
obj.disp()
//子类只能继承一个父类,TypeScript 不支持继承多个类,但支持多重继承,如下实例:
class Root { str:string; }
class Child extends Root {}
class Leaf extends Child {} // 多重继承,继承了 Child 和 Root 类
var obj = new Leaf();
obj.str ="hello"
console.log(obj.str)
类继承方法重写
class PrinterClass {
doPrint():void {
console.log("父类的 doPrint() 方法。")
}
}
class StringPrinter extends PrinterClass {
doPrint():void {
super.doPrint() // 调用父类的函数
console.log("子类的 doPrint()方法。")
}
}
static
/*
静态属性, 是类对象的属性。即可以用类名直接访问
非静态属性, 是类的实例对象的属性。即通过实例化对象访问
*/
class Person {
name1: string = 'A'
static name2: string = 'B'
constructor(a1:string, a2:string) {
this.name1 = a1 //不会报错
this.name2 = a2 //报错,this指向实例化对象,而namd2是静态属性,属于类对象的。
}
}
console.log(Person.name2)
console.log(new Person().name1)
instanceof 运算符
class Person{ }
var obj = new Person()
var isPerson = obj instanceof Person;
console.log("obj 对象是 Person 类实例化来的吗? " + isPerson);
访问控制修饰符
- public(默认) : 公有,可以在任何地方被访问。
- protected : 受保护,可以被其自身以及其子类访问。
- private : 私有,只能被其定义所在的类访问。
class Encapsulate {
str1:string = "hello"
private str2:string = "world"
}
var obj = new Encapsulate()
console.log(obj.str1) // 可访问
console.log(obj.str2) // 编译错误, str2 是私有的
类实现接口
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 )
泛型
泛型指的是在定义函数/接口/类型时,不预先指定具体的类型,而是在使用的时候在指定类型限制的一种特性。
function test <T> (arg:T):T{
console.log(arg);
return arg;
}
test<number>(111);// 返回值是number类型的 111
test<string | boolean>('hahaha')//返回值是string类型的 hahaha
test<string | boolean>(true);//返回值是布尔类型的 true
//接口中使用泛型
// 注意,这里写法是定义的方法哦
interface Search {
<T,Y>(name:T,age:Y):T
}
let fn:Search = function <T, Y>(name: T, id:Y):T {
console.log(name, id)
return name;
}
fn('li',11);//编译器会自动识别传入的参数,将传入的参数的类型认为是泛型指定的类型
//类中使用泛型
class Animal<T> {
name:T;
constructor(name: T){
this.name = name;
}
action<T>(say:T) {
console.log(say)
}
}
let cat = new Animal('cat');
cat.action('mimi')
使用接口约束泛型
interface Person {
name:string;
age:number;
}
function student<T extends Person>(arg:T):T {
return arg;
}
student({name:'lili'});//类型 "{ name: string; }" 中缺少属性 "age",但类型 "Person" 中需要该属性
student({ name: "lili" , age:'11'});//不能将类型“string”分配给类型“number”
student({ name: "lili" , age:11});
数组泛型
let arr:Array<number> =[1,2,3] === let arr:number[]=[1,2,3]
泛型工具类型
partial<T>的作用就是将某个类型中的属性全部变为可选项?
Record<K extends keyof any, T>的作用是将K中所有的属性转换为T类型
Pick<T, K extends keyof T>的作用是将某个类型中的子属性挑出来,变成包含这个类型部分属性的子类型
Exclude<T,U>的作用是将某个类型中属于另一个类型的属性移除掉
returnType<T>的作用是用于获取函数T的返回类型
命名空间
namespace SomeNameSpaceName {
export interface ISomeInterfaceName { }
export class SomeClassName { }
}
如果一个命名空间在一个单独的 TypeScript 文件中,则应使用三斜杠 /// 引用它,语法格式如下:
//IShape.ts 文件代码:
namespace Drawing {
export interface IShape {
draw();
}
}
//Circle.ts 文件代码:
/// <reference path = "IShape.ts" />
namespace Drawing {
export class Circle implements IShape {
public draw() {
console.log("Circle is drawn");
}
}
}
//Triangle.ts 文件代码:
/// <reference path = "IShape.ts" />
namespace Drawing {
export class Triangle implements IShape {
public draw() {
console.log("Triangle is drawn");
}
}
}
//TestShape.ts 文件代码:
/// <reference path = "IShape.ts" />
/// <reference path = "Circle.ts" />
/// <reference path = "Triangle.ts" />
function drawAllShapes(shape:Drawing.IShape) {
shape.draw();
}
drawAllShapes(new Drawing.Circle());
drawAllShapes(new Drawing.Triangle());
模块
//命名空间引入
/// <reference path = "IShape.ts" />
export interface IShape {
draw();
}
引入模块
import shape = require("./IShape");
export class Circle implements shape.IShape {
public draw() {
console.log("Cirlce is drawn (external module)");
}
}