目录
public、private、protected --- 类的实例成员
基础类型
boolean、number、string、Array、Tuple、enum、any
空值(void)、undefined、null、never
数组 -- Array
// 方式一
let arr1: number[] = [1,2,3,4]
// 方式二
let arr2: Array<number> = [1,2,3]
任意值 -- any
给不确定类型的变量指定一个类型
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay
枚举类型 -- enum
// 创建enum实例
enum Color {
Red = 1,
Green,
Blue,
}
//通过.key 取value
let num: Color = Color.Red;
console.log("num: ", num) //1
//通过value取key,前提是value是数字且不要有重复的值
let colorName: string = Color[2];
console.log("colorName: ", colorName) //Green
变量声明
1.对象展开会丢失其方法
class C {
p = 12;
m() {
}
}
let c1 = new C();
let c2 = { ...c1 };
console.log(c2.p); // 12
c2.m(); // error!
接口
TypeScript的核心原则之一就是对值所具有的结构进行类型检查。
可选属性
接口里的属性不全都是必需的,有些是只在某些条件下存在。但是不能定义接口不存在的属性
- 可以对可能存在的属性进行预定义
- 可以捕获引用了不存在的属性时的错误
//定义两个参数,且两个参数非必传
interface ArgConfig {
color?: string;
width?: number;
}
function test(arg: ArgConfig){
console.log(arg)
}
test({color: "red", width: 10})
test({color: "red"})
test({width: 10})
test({height: 10}) //error
定义函数返回值
// 冒号后面定义返回值结构
function axios(arg: string): { msg?: string; code: number; data: any }{
return {code: 200, data: {}, msg: "成功"}
}
let result = axios("/api/getData")
只读属性
- readonly -- 定义属性从创建之后不能被修改
- ReadonlyArray -- 定义数组从创建之后不能被修改
//方式一
interface point{
readonly x: number,
readonly y: number,
}
let point1: point = {x: 1.23, y: 2.45}
point1.x = 3 //error
//方式二
let point: ReadonlyArray<number> = [1,2,3]
point.push(4) //array
readonly与const的区别
如果时属性不可修改,就用readonly
如果是变量不可修改,就用const
检查额外的属性
当参数被检测到有额外的参数被传入时,ts会报错,如下
//定义两个参数,且两个参数非必传
interface ArgConfig {
color?: string;
width?: number;
}
function test(arg: ArgConfig){
console.log(arg)
}
test({height: 10}) //error 未定义height参数
最简便的方法是使用类型断言
test({height: 10} as ArgConfig) //okey
函数类型
作用:定义参数和返回值类型,对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配,只需要同等位置上的类型对应就可以通过
// 参数 a、b、c ; 返回值是对象 {res: boolean, code: number}
interface func {
(a: number, b: number, c?: number): {res: boolean, code: number}
}
let test: func; //定义函数类型
test = function(x: number, y: number){
return {code: 200, res: x>y}
}
console.log(test(3, 1)) //true
可索引类型
描述那些可以通过索引得到的类型,比如a[0] 、b["red"]
可索引类型具有一个索引签名,他描述了索引的类型和相应索引返回值类型
索引签名:有两种,数字和字符串,可同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值的子类型。因为当使用数字去索引时,ts会把数字转为字符串去索引,因此两者需要保持一致
interface Indexes{
[index: number]: string
}
let test: Indexes;
test = ["aa", "bb"]
test = ["aa", "bb", 0] //error 因为0不是string类型
类
public、private、protected --- 类的实例成员
- 默认成员为public
- private需要特别声明,派生类和外部变量无法访问;
- protected需要特别声明,派生类可以访问,外部变量无法访问; 如果构造函数被标记为protected(protected constructor()),则不能被实例化,可以被继承
class Animal {
name: string;
private age: number;
protected score: number;
constructor(theName: string, theAge: number = 10, score: number = 0) {
this.name = theName;
this.age = theAge;
this.score = score
}
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
getAge() {
console.log("age: ", this.age)
return this.age;
}
}
class Horse extends Animal {
// 派生类的构造函数必须包含 "super" 调用,执行super()后,才能使用this
constructor(name: string) {
super(name);
console.log("Horse name: ", this.name);
}
move(distanceInMeters = 45) {
super.move(distanceInMeters);
}
getScore(){
console.log("score: ", this.score)
}
}
let tom = new Horse("Horse");
tom.move();
tom.getAge()
tom.getScore()
// Horse name: Horse
// Horse moved 45m.
// age: 10
// score: 0
let animal = new Animal("bird") //error! 构造函数被标记为protected,不能被实例化
static --- 只属于类本身
只属于类本身,不属于类的实例
每个实例想要访问这个属性时,需要在前面加上类的名称,这里使用Animal
class Animal {
static age = 10
constructor (public name: string) { }
userInfo(){
return `名称:${this.name} 年龄:${Animal.age}`
}
}
let animal = new Animal('ddu');
console.log(animal.userInfo())
// 名称:ddu 年龄:10
readonly
只读属性只能在声明或构造函数里被初始化
class Animal {
readonly name: string;
readonly age: number = 10; //声明
constructor(theName: string) { //构造函数
this.name = theName;
}
}
let dog = new Animal("Dog");
console.log(dog.age)
dog.age = 20 // Error! 只读属性不能设置
参数属性
变量声明与赋值(constructor)二合一,需要声明public、private、protected
class Animal {
constructor(public name: string) { //构造函数
}
}
let dog = new Animal("Dog");
console.log(dog.name) //Dog
存取器
我们可以调用对象随意的设置变量,但这可能会带来麻烦。所以我们可以捕获set操作,做校验。
- 只带有get,没有set的存取器被推断为readonly
class Account {
private _password: string = "12345";
get password(): string {
console.log("get")
return this._password;
}
set password(newValue: string){
console.log("set")
if(newValue.length >= 5){
this._password = newValue
}
else{
console.log("error passord")
}
}
}
let account = new Account()
console.log(account.password)
// get
// 12345
account.password = "789123"
// set
abstract --- 抽象类、抽象方法
// 抽象方法,定义方法但不定义方法体,必须在派生类中实现
函数
函数写法
函数分为有名字得函数和匿名函数,且定义类型时需要定义参数类型和返回值类型
function add(x: number, y: number): number {
return x + y;
}
//匿名函数
let myAdd = function(x: number, y: number): number { return x + y; };
声明函数类型
可以先声明函数类型再赋值,也可以在声明类型的同时赋值,类似其他基础类型
let a: string = 'more'
//声明类型
let myAdd: (firstValue: number, secondValue: number) => number
//赋值
myAdd = function(x: number, y: number): number { return x + y; };
剩余参数
函数传参的个数有时可能不确定,此时可以用剩余参数的方法,把参数放到一个变量数组中。剩余参数接受0~多个参数
function stringJoin(firstName: string, ...nameList: Array<string>) {
return firstName + " " + nameList.join(' ');
}
let names = stringJoin("Bob", "xs", 'mriao'); //Bob xs mriao
this...
泛型
泛型函数
当我们需要函数参数类型和返回值类型一致时,我们可以使用变量T代替类型,这样就可以适用于多个类型 ------- 泛型变量法
//创建T类型
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("myString");//调用
//创建T类型的数组
function identity<T>(arg: T[]): T[] {
return arg;
}
let output = identity<number>([1,2,3]);
与非泛型函数的区别:前面增加了一个类型声明 <类型变量>
函数本身类型
声明函数类型
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: <A>(arg: A) => A = identity
泛型接口
//写法一
interface GenericIdentity{
<A>(arg: A) : A
}
let myIdentity: GenericIdentity = identity
//写法二
interface GenericIdentity<A>{
(arg: A) : A
}
let myIdentity: GenericIdentity<string> = identity
泛型类
泛型类类名后跟<>,写入泛型
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
泛型约束
有时我们希望传入的类型具有某个特性,并不想接收所有的类型,此时可以使用接口继承去约束
interface length{
length: number;
}
interface GenericIdentity<A extends length>{
(arg: A) : A
}
function identity<T>(arg: T): T {
return arg;
}
let stringIdentity: GenericIdentity<string> = identity
let numberIdentity: GenericIdentity<number> = identity //Erroe, number没有length属性