TypeScript
数据类型
typeScript中的数据类型
-
typescript中为了使编写的代码更规范,更有利于维护,增加了类型校验**
-
写ts代码必须指定类型
- 布尔类型(boolean)
var flag:boolean = true;
// flag = 123 // 错误
flag = false;
console.log(flag)
- 数字类型(number)
var num: number = 123;
num = '4564' // 错误
num = 4564 // 正确
console.log(num);
- 字符串类型(string)
var str:string = '111' // 正确
var str:string = 111 // 错误
- 数组类型(array)
// 1.第一种定义数组方式
// var arr:number[] = [11,22,33]
// console.log(arr);
// 2.第二种定义数组方式
var arr:Array<number> = [11,22,33]
console.log(arr);
- 元组类型(tuple) 属于数组的一种 ==> 一项对应一种类型
let arr: [number,string,number] = [123,'this is ts',456];
console.log(arr);
枚举类型(enum)
enum flag {
success=1, error=2
}
let s:flag=flag.success
console.log(s); // 1 如果标识符没有赋值 它的值就是下标
- 任意类型(any)
var arr: any = [123, '123', true, '', null]
console.log(arr);
用处:
如获取dom节点时,可以使用 any 声明变量保存节点
-
null和undefined
-
void类型
function run():void {
// return 1 报错
console.log('run');
}
run()
- never类型:是其他类型(从来不会出现的值)
var a: never;
// a=123 错误写法
a = (() => {
throw new Error('错误')
})()
函数
typeScript中的函数
- 函数的定义
// 函数声明
function run(): string{
return 'run';
}
// 函数表达式
var run2 = function(): number{
return 123;
}
run()
run2()
// 传参
function getInfo(name: string, age: number): string{
return `name=${name},age=${age}`
}
console.log(getInfo('lc',12));
- 可选参数(es5中方法的实参和形参可以不一样,但是ts中必须一样,如果不一样就需要配置可选参数)
* 注意:可选参数必须配置到参数的最后面
function getInfo(name: string, age?: number): string {
return age ? `name=${name},age=${age}` : `name=${name}`
}
console.log(getInfo('lc', 20)); // name=lc,age=20
console.log(getInfo('lc')); // name=lc
- 默认参数
function getInfo(name: string, age: number = 10): string {
return age ? `name=${name},age=${age}` : `name=${name}`
}
console.log(getInfo('lc', 20)); // name=lc,age=20
console.log(getInfo('lc')); // name=lc,age=10
- 剩余参数
function sum(...result: number[]): number {
var sum = 0;
for (var i = 0; i < result.length; i++) {
sum += result[i]
}
return sum
}
console.log(sum(1, 2, 3, 4));
- 函数重载
function getInfo(name: string): string;
function getInfo(age: number): number;
function getInfo(str: any): any {
if (typeof str === 'string') {
return '我是' + str
} else {
return '年龄是' + str
}
}
console.log(getInfo('11'));
类
typeScript里的类
- 类的定义
class Person {
name: string; // 属性 前面省略了public关键词
constructor(name: string) { // 构造函数
this.name = name
}
getName(): string {
return this.name
}
setName(name: string): void {
this.name = name
}
}
var p = new Person('张三')
console.log(p.getName());
- 继承
class Person {
name: string;
constructor(name: string) {
this.name = name
}
run(): string {
return `${this.name}在运动`
}
}
class Web extends Person {
constructor(name: string) {
super(name)
}
}
var w = new Web('李四')
console.log(w.run());
- 类里面的修饰符(ts提供了三种修饰符) 默认是公有
// public 公有 在类里面、子类、类外都可以访问
class Person {
public name: string;
constructor(name: string) {
this.name = name
}
run(): string {
return `${this.name}在运动`
}
}
var p = new Person('说说')
// 类外部访问公有属性
console.log(p.name);
// protected 保护 在类里面、子类都可以访问,类外没法访问
class Person {
protected name: string;
constructor(name: string) {
this.name = name
}
run(): string {
return `${this.name}在运动`
}
}
var p = new Person('说说')
// 类外部访问公有属性
// console.log(p.name); // 错 Property 'name' is protected and only accessible within class 'Person' and its subclasses.
class Web extends Person {
constructor(name: string) {
super(name)
}
}
var w = new Web('李四')
console.log(w.run()); // 李四在运动
// private 私有 在类里面可以访问,子类、类外都没法访问
class Person {
private name: string;
constructor(name: string) {
this.name = name
}
run(): string {
return `${this.name}在运动`
}
}
var p = new Person('说说')
// 类外部访问公有属性
// console.log(p.name); //Property 'name' is private and only accessible within class 'Person'.
class Web extends Person {
constructor(name: string) {
super(name)
}
work(){
console.log(this.name); //Property 'name' is private and only accessible within class 'Person'.
}
}
var w = new Web('李四')
console.log(w.run()); // 李四在运动
-
静态属性 静态方法
静态方法不能直接调用类里面的属性,可以调用静态属性
-
抽象类 继承 多态
// 多态:(属于继承) 父类定义一个方法不去实现,让继承它的子类去实现,每一个子类有不同的表现
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat() { // 父类eat方法,不去实现,具体吃什么 不知道,具体吃什么?继承它的子类去实现,每一个子类的表现不一样
console.log('吃的方法');
}
}
class Dog extends Animal {
constructor(name: string) {
super(name)
}
eat() { // 子类eat方法,去实现
return this.name + '吃肉'
}
}
class Cat extends Animal {
constructor(name: string) {
super(name)
}
eat() { // 子类eat方法,去实现
return this.name + '吃🐟'
}
}
var d = new Dog('旺仔')
var c = new Cat('小花')
console.log(d.eat());
console.log(c.eat());
// 抽象类:它是提供其他继承的基类,不能直接被实例化
// 用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现
// abstract抽象方法只能在抽象类里面
// 抽象类和抽象方法定义标准 eg:Animal类是所有动物类的基类,定义了子类的标准
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
abstract eat(): any;
}
// var a = new Animal() // Cannot create an instance of an abstract class.
class Dog extends Animal {
// 抽象类的子类必须实现抽象类里面的抽象方法
constructor(name:string){
super(name)
}
eat() {
console.log(this.name+'吃骨头');
}
}
var d = new Dog('旺仔')
d.eat();
接口
typeScript中的接口
接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,他只规定这批类必须提供某些方法,提供这些方法的类就可以满足实际需求,
- 属性接口
interface FullName {
firstName: string;
secondName: string;
}
function printName(name: FullName) {
// 必须传入对象 firstName secondName
console.log(name.firstName + '---' + name.secondName);
}
// printName('123') // 报错 Argument of type '"123"' is not assignable to parameter of type 'FullName'.
var obj = {
age: 20,
firstName: '张',
secondName: '三'
}
printName(obj)
// 可选属性接口
interface FullName {
firstName: string;
secondName?: string; // 可选属性
}
function getName(name: FullName) {
// 必须传入对象 firstName secondName
console.log(name);
}
getName({
firstName: 'firstName'
})
getName({
firstName: 'firstName',
secondName: 'secondName'
})
- 函数类型接口:对方法传入的参数以及返回值进行约束
// 加密的函数类型接口
interface encrypt {
(key: string, value: string): string;
}
var md5: encrypt = function (key: string, value: string): string {
return key + value
}
console.log(md5('name', 'zhangsan'));
- 可索引接口:数组、对象的约束(不常用)
// 数组的约束
interface UserArr {
[index: number]: string // 规定:索引为number,值为string
}
var arr:UserArr=['1','2']
console.log(arr[1]);
// 对象的约束
interface UserObj {
[index: string]: string // 规定:key为string,value为string
}
var obj:UserObj={name:'20',age:'20'}
console.log(obj);
- 类类型接口
interface Animal {
name: string;
eat(str: string): void
}
class Dog implements Animal {
name: string;
constructor(name: string) {
this.name = name
}
eat() {
console.log(this.name + '吃粮食');
}
}
var d = new Dog('小黑')
d.eat()
- 接口扩展:接口可以继承接口
interface Animal {
eat(): void;
}
interface Person extends Animal {
work(): void;
}
// Web类必须实现eat和work方法
class Web implements Person {
public name: string;
constructor(name: string) {
this.name = name
}
eat() {
console.log(this.name + '喜欢吃馒头');
}
work() {
console.log(this.name + '在工作');
}
}
var w = new Web('小磊')
w.work()
泛型
typeScript的泛型
- 泛型的定义
-
泛型:软件工程中,我们不仅要创建一致良好的API,同时也要考虑重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
-
在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。
-
通俗理解:泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验),性能上比any数据类型性能高
-
泛型:可以支持不特定的数据类型, 要求:传入参数和返回的参数一致
- 泛型函数
// T表示泛型,具体什么类型是调用这个方法的时候决定的
function getData<T>(value: T): T {
return value
}
getData<number>(123);
// getData<number>('123'); // 错误写法
- 泛型类:比如有个最小堆算法,需要同时支持返回数字和字符串两种类型。 通过类的泛型类实现
class MainClass<T>{
public list: T[] = [];
add(num: T): void {
this.list.push(num)
}
min(): T {
var minNum = this.list[0]
for (var i = 0; i < this.list.length; i++) {
if (minNum > this.list[i]) {
minNum = this.list[i]
}
}
return minNum
}
}
var m = new MainClass<number>() //实例化类 并且指定了类的T代表了number
m.add(1)
m.add(2)
m.add(3)
console.log(m.min());
var m1 = new MainClass<string>() // 实例化类 并且指定了类的T代表了string
m1.add('2')
m1.add('3')
console.log(m1.min());
- 泛型接口
// 方式一
interface Config {
<T>(value: T): T;
}
var getData: Config = function <T>(value: T): T {
return value
}
getData<string>('张三');
getData<number>(123);
//方式二
interface Configfn<T> {
(value: T): T;
}
function Data<T>(value: T): T {
return value
}
var mygetData1:Configfn<string> = Data
var mygetData2:Configfn<number> = Data
mygetData1('20')
mygetData2(20)