鸿蒙开发大部分开发是移动设备的,但是移动端的开发也可以使用网页开发的技术去实现,但是需要三种基础,分别是HTML,CSS,JavaScript等,写出来的话,过于繁琐(当然也可以使用其他的前端框架),避免这些繁琐的内容,可以依靠ArkTs

什么是ArkTs

ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集
在这里插入图片描述

什么是TypeScript

JavaScript:动态类型语⾔(Dynamically Typed Language),在运⾏期间检查数据的类型的
语⾔。⽤这类语⾔编程,不会给变量指定类型,⽽是在赋值时得到数据类型。

TypeScript是微软开发的⼀个开源的编程语⾔,通过在JavaScript的基础上添加静态类型定义构
建而成

TypeScript增加了什么
● 类型
● 完美⽀持ES新特性
● 添加ES不具备的新特性
● 丰富的配置选项
● 强⼤的开发⼯具

全局安装TS
1.进⼊DOS界⾯
2.输⼊:npm i -g typescript
3.验证:tsc -v
将ts⽂件编译成js⽂件 tsc test.ts

// 案例一:
var a = 123
a='yuanzi'
a=true

// 案例二:
funcation fn(){
  console.log(1)
}

TypeScript中简单的数据类型

类型声明 [变量名:类型]

  • 类型声明是TS中⾮常重要的特点
  • 通过类型声明可以指定TS中变量(形参)的类型
  • 指定类型后,当变量赋值时,TS编译器就会⾃动检查值是否符合声明类型,如果符合就赋值,不符合就报错
  • 简单的说,类型声明就是给变量设置了类型。使得变量只能存储某种类型的值
  • 变量类型 :number boolean array string object

语法:

// 类型声明:
//  let 变量名:类型;//只声明,未赋值
//  let 变量名:类型=值;//声明并赋值 
//  function fun(参数:类型,参数:类型):类型{
//  }


//变量类型    number boolean array string object


let b:number;//声明了变量b,指定了类型
b=123;//给b赋值123
// b='yuanzi';  //因为给了他number类型,b赋值了之后不能再赋值其他类型了


// 声明并赋值
let c:boolean=true;


// 形参声明类型
function fun(name:string){
    console.log(name);
}
// fun(123);

console.log(b+'=b');
console.log(c+'=c');

fun('yuanzi');

自动类型判断

  • TS拥有⾃动类型判断机制
  • 对变量的声明和赋值同时进⾏时,TS编译器会⾃动判断变量类型
  • 所以如果你的变量的声明和赋值是同时进⾏的,可以省略掉类型声明
let a:number=123;

//这个说明给这个b设置了number这个类型
let b=23;
// b='yuanzi';//因为是字符串,类型定义的是number类型,赋值的话就会报错

console.log(typeof a);
console.log(typeof b);

字面量

字⾯量:是个客观存在⽆法改变的值。例如: 1 2 3 4 5 6 true ‘hello’

//使⽤字⾯量声明后a的值,永远是12 相当于常量不能修改
let c:12;
// c=13;

const b=12;

any

any:表示任意数据类型⼀个变量设置类型为any后相当于对该变量关闭了TS的类型检测

使用any存在的隐患:

  • 使用any声明的变量不仅会影响到自己也会影响到别人
  • 不同类型的变量值赋值之后,也会改变被赋值的变量类型
let a:any;//显式的any类型声明
a=123;
a='yuanzi';
a=true;

let b;//隐式的any 如果不设定类型,自动判断该变量的类型是any
b=123;
b=true;
b='yuanzi';


let c:number;
c=12;
c=b;

console.log(typeof a);//any
console.log(typeof b);//any
console.log(typeof c);//any

TS的unknow(安全的any)

let a:unknown;
a=123;
a='yuanzi';
a=true;//只会打印出最后一个

let b:boolean;

//这个时候我想赋值给b,如下
// b=a; 
// 此时ts解析会报错,
// 虽然a b变量中的字面量都是string
// 但是a 是string类型  b是unknown类型 所以不能赋值


//也可以使用这种办法
if(typeof a ==='boolean'){
    b=a;//直接可以赋值了
}

console.log(a);//true
console.log(b);//true

TS的类型断言

类型断⾔:可以⽤来告诉TS解析器变量的实际类型

语法:<font style="color:rgb(0,0,0);">变量 as 类型</font>

let a:unknown;
a=123;

let b:number;

// 可以处理上一个问题
if(typeof a ==='boolean'){
    b=a;//直接可以赋值了
}

// 可以利用类型断言来处理解决unknow赋值问题
b= a as number;

TS的函数

对函数中形参进⾏类型声明,

  • 按照函数声明的形参类型传递参数
  • 形参和实参数量一致
 function fun(形参1:number,形参2:number){
     console.log(形参1+形参2);
 }

 //调⽤
 //传递不是number的实参
//TS解析器提示报错,不允许这样做,我们必须按照函数声明的形参类型传递参数
 fun('yuanzi','net');
 fun(123,456);//正确的参数
 fun(123,4556,55,56);//多参数 TS解析器报错
 fun(11);//少参数 TS解析器报错
//对函数中形参进行类型声明  
function fun1(age:number){
    console.log(age);
}
fun1(18);


function fun2():string{
    return "123";
}

let a=fun2();
console.log("a="+ typeof a);

函数中返回值类型的声明

第⼀种情况:不设置返回值类型,但是有返回值(undefined)

// 不设置返回值类型,但是有返回值 undefined 
function fun2(){}
let a = fun2();

//这个时候ts解析器会根据返回值的类型进行判断,返回值的类型是什么函数返回值类型就是什么
console.log("a="+ typeof a);

第二种情况:设置返回值类型为void(用来表示空,以函数为例,就表示没有返回值的函数)

  • 不能传递字符,字符串,对象,数组,或者布尔值
function fun3():void{
    // return 'a';//报错
    // return 112;//报错
    // retrun 'yuanzi';//报错
    // return true;//报错
    // return NaN;//报错
     return null; //ok  可以返回
     return undefined;// ok 可以返回
    // return ;
}

第三种情况:设置返回值类型为never(永远不会返回结果)

function fun4():never{
    //程序报错代码立马结束,立即结束以后就不会返回值了
    throw new Error("提示信息!!");
}
let d=fun4();
console.log("d="+d);

TypeScript中复杂的数据类型声明

对象的类型声明

object表示⼀个对象

//声明一个变量,类型为Object,相当于a用来保存一个对象
let a:object;

a={};
a=function(){};
//这2个没有限制,而且不实⽤,因为在js中对象太多了,⼀切皆为对象。

这样写表示声明⼀个变量b 类型为对象,对象中只能有⼀个属性为名为name且属性值的类型为string

let b:{name:string};
b={name:'yuanzi'};

b={}//提示报错
b={name:'yuanzi'}

用来指定对象中可以包含哪些属性 严格按照指定对象的格式

需求一:我们指定的对象它必须包含一个name,但是还有age和sex这个俩个变量是可能有可能有没有的,这种情况我们该怎样做呢?
可以使用 属性?:类型

let c:{
    name:string,
    age?:number,
    sex?:string
}

c={
   name:'yuanzi',
   age:18
}

需求二:当我们只知道我们必须有的属性,而其他的不必须我们不知道,我们该怎么处理呢?

可以通过以下方式实现,指定b中的存储类型是对象,并且这个对象必须含有一个name的属性,类型为string,这个对象还可以有其他可选属性,只要属性名满足字符串,属性值是unknown即可

let b:{name:string, [propName : string] : unknown}

// let propName:string;
// propName='yuanzi';
// propName='园子';
//这个任意命名,表示属性的名字,这个属性名字的类型是string,js中属性名一般都是用string定义
//[propName:string]

let d:{
    name:string,
    //合起来代表属性名为string类型,且可选的并且这个属性的值为unknown类型
    [propName:string]:unknown
}


d={
    name:'yaunzi',
    sayHello(){
        console.log(this.name);
    }
}

console.log(d.name);
if (typeof d.sayHello === 'function'){
    d.sayHello();
}

数组类型声明

数组类型声明的语法

第一种: let 变量名:类型名[ ]

第二种: let b:变量名<类型名>;

//声明一个数组 string[]表示字符串数组 所以里面只能是字符串
let a:string[];
a[0]='yuanzi';
// a[1]=true;//报错


//类型声明只能是boolean
let b:Array<boolean>;
b[0]=false;
// b[0]='yuanzi';//报错

// 如果想要创建一个任意类型的数组
let e:Array<any>
let e:any[]

扩展类型tuple

tuple:叫做元组

语法:[类型,类型, 类型]

元组 : 定⻓的数组

(就代表数组中的数量是固定的就叫做元组,元组的存储效率⽐较好点,因为元组是固定,不会出现扩容的现象,所有效率会好点)

// 扩展类型tuple(元祖  定长的数组 固定的)

//定义一个元祖,必须按照声明的结构定义数组,不然解析器会提示报错
let a:[string,boolean,number];
a=['yuanzi',true,123];
console.log(a);//'yuanzi',true,123

TS中Enum

enum(枚举): 一个特殊的对象

在数学和计算机科学理论中,⼀个集的枚举是列出某些有穷序列集的所有成员的程序,或者是⼀种特定类型对象的计数

TS中的枚举Enum:定义⼀些带名字的常量。⽤于清晰地表达意图或创建⼀组有区别的⽤例

语法: enum 枚举名称{成员1,成员2…};

//数字枚举
enum a{
    //
    male=0,
    female
};

console.log(a.male);
console.log(a.female);//刚开始定义的时候并没有赋值,他会自动加一
//字符串枚举
enum b{
    red='红',
    yellow='黄',
    blue='蓝'
}

console.log(b.red);
console.log(b.yellow);
console.log(b.blue);

TS中的联合类型声明

使⽤“|” 进⾏联合类型声明

语法:let 变量名:变量类型1|变量类型2;

let a:number|string;
a=123;
a='yuanzi';


//限制b的范围,b只能是12 13 14 15 如果是其它的报错
let b:12|13|14|15;
b=12;
b=15;
// b=16;//报错

TS中类型别名

简化我们书写的代码

语法: type 类型别名的名字 = 声明类型别名

// 如果变量a b的取值范围是一样的,如果还有其他十几个变量的取值范围也是一样的,怎么办
// let a:1|2|3|4|5|6|7|8|9|10;
// let b:1|2|3|4|5|6|7|8|9|10;

type myType=1|2|3|4|5|6|7|8|9|10;
// 使用类型别名来优化
let a:myType;
let b:myType;

a=1;
b=2;

console.log(typeof a);
console.log(typeof b);

TypeScript的配置

如何开启⾃动编译ts⽂件的功能

⾃动编译单个⽂件

编译⽂件时,使⽤-w指令后,TS编译器会⾃动监视⽂件的变化,并在⽂件发⽣改变时对⽂件进⾏重新编译。

tsc 文件名.ts -w

⾃动编译当前项⽬下的所有的ts⽂件

  • 如果直接使⽤tsc指令,则可以⾃动将当前项⽬下的所有的ts⽂件编译成js⽂件
  • 有⼀个前提,⾸先在项⽬的根⽬录下创建⼀个ts的配置⽂件 tsconfig.json
  • tsconfig.json是⼀个json⽂件,添加配置后,只需要tsc命令即可完成对整个项⽬的编译

1.创建一个ts的配置文件 tsconfig.json

2.使用tsc命令

详解tsconfig.json中的配置选项

// tsconfig.json 
{
    // "include": ["./dev"],
    // "exclude": ["./prop/**/*"]
    // "extends": "./config/base"
    // "files": ["./dev/devDemo.ts"]
    // "compilerOptions": {
        // "target": "ES6",
        // "module": "amd",
        // "lib": ["DOM"]
        // "outDir": "./dist",
        // "outFile": "./dist/app.js",
        // "allowJs": true,
        // "checkJs": true
        // "removeComments": true,
        // "noEmit": true,
        // "noEmitOnError": true,
        // "alwaysStrict":true
        // "noImplicitAny":true,
        // "strictNullChecks":true
        // "strict": true

    }
}

include

定义希望被编译⽂件所有的⽬录(更目录(tsconfig.json所在的目录)所有的ts文件都会被编译)

默认值:[/]

 "include":["dev/**/*","prop/**/*"]
 // **:表示任意⽬录
 // *:表示任意⽂件
 //就代表所有的dev⽬录和prop⽬录下的⽂件都会被编译

exclude

定义不需要编译的⽬录

// 默认值:
["node_modules","bower_components","jspm_packages"]
// 案例:
"exclude":["./prop/**/*"]
//代表不编译prop⽬录下的所有⽂件

extends:

定义被继承的配置⽂件

 "extends":"./config/base"
//表示当前配置⽂件会⾃动包含config⽬录下base.json中的所有配置信息

files:

指定需要编译⽂件的列表(很少使用,一般用在文件毕竟较少的时候)

 "files":[
           "one.ts",
           "two.ts",
           "three.ts",
           "four.ts"
         ]
 // 表示列表中⽂件都会被TS编译器编译

complierOptions :

ts编译时的配置

详解tsconfig.json中的complierOptions

  • target:指定ts编译的js⽬标版本
// 可选值:"ES3"(默认), "ES5", "ES6"/ "ES2015", "ES2016", "ES2017"或 "ESNext"。
// 案例:
 "compilerOptions":{
    "target":"ES6"
 }
 //表示我们所编写的ts代码将会被编译ES6版本的js代码
  • module:指定使⽤的模块化规范:
// 可选值:
//  "None", "CommonJS", "AMD", "System", "UMD", "ES6"或 "ES2015"。
// ▶ 只有 "AMD"和 "System"能和 --outFile⼀起使⽤。
// ▶ "ES6"和 "ES2015"可使⽤在⽬标输出为 "ES5"或更低的情况下。
  • lib:指定编译过程中需要引⼊的库⽂件的列表
// 可选值
//  ▶ ES5
//  ▶ ES6
//  ▶ ES2015
//  ▶ ES7
//  ▶ ES2016
//  ▶ ES2017
//  ▶ ES2018
//  ▶ ESNext
//  ▶ DOM
//  ▶ DOM.Iterable
//  ▶ WebWorker
//  ▶ ScriptHost
//  ▶ ES2015.Core
//  ▶ ES2015.Collection
//  ▶ ES2015.Generator
//  ▶ ES2015.Iterable
//  ▶ ES2015.Promise
//  ▶ ES2015.Proxy
//  ▶ ES2015.Reflect
//  ▶ ES2015.Symbol
//  ▶ ES2015.Symbol.WellKnown
//  ▶ ES2016.Array.Include
//  ▶ ES2017.object
//  ▶ ES2017.Intl
//  ▶ ES2017.SharedMemory
//  ▶ ES2017.String
//  ▶ ES2017.TypedArrays
//  ▶ ES2018.Intl
//  ▶ ES2018.Promise
//  ▶ ES2018.RegExp
//  ▶ ESNext.AsyncIterable
//  ▶ ESNext.Array
//  ▶ ESNext.Intl
//  ▶ ESNext.Symbol
// 案例:
//  "compilerOptions":{
//  "target":"ES6",
//  "lib":["ES6","DOM"]
//  }
// 注意:如果--lib没有指定默认注⼊的库的列表。默认注⼊的库为:
// ▶ 针对于--target ES5:DOM,ES5,ScriptHost
// ▶ 针对于--target ES6:DOM,ES6,DOM.Iterable,ScriptHost

outDir:⽤来指定编译后⽂件所在的⽬录

// 案例:
//  "compilerOptions":{
//  "target":"ES6",
//  "lib":["ES6","DOM"],
//  "outDir":'./dist'
//  }

outFile:将编译的代码合并成⼀个⽂件

// 案例:
//  "compilerOptions":{
//  "target":"ES6",
//  "lib":["ES6","DOM"],
//  "outDir":'./dist',
//  "outFile":'./dist/main.js'
//  }
// "outFile":'./dist/main.js'
// //就表示把编译后的⽂件合并的main.js这⽂件中,最后只会输出⼀个js⽂件
// 出现问题的解决⽅案:
 
//  mudule只能使⽤ amd或者是system
 
 
// 其实outFile这个功能我们在⼯作中也很少使⽤,
// 因为我们打包的时候都是通过打包⼯具进⾏使⽤的。
// 所以这个outFile⼤家知道有这个东⻄了解⼀下就⾏

allowJs :是否对js⽂件进⾏编译

// 默认值:false
// 案例:
//  "allowJs":true

checkJs:是否检查js代码符合语法规范

// 默认值:false
// 案例:
//  "checkJs":true

removeComments:在编译的时候是否移除注释

// 默认值:false

noEmit:不⽣成编译后的⽂件

// 默认值为:false
// 案例:
//  "noEmit":true
// //这个有什么⽤呢,可能有时候你就想⽤ts的语法检测。就可以使⽤这个

noEmitOnError:当存在语法错误的时不⽣成编译后的⽂件

// 默认值:false
// 案例:
//  "noEmitOnError":true

alwaysStrict :设置编译后的⽂件是否使⽤严格模式

// js中有⼀种模式叫做严格默认,它语法更严格,在浏览器执⾏的性能更⾼,开发时候我们都会让我们的代码
// 在严格模式下执⾏
// 如果是在js⽂件的话 只需要在js⽂件的开头加⼊⼀个字符串
// "use strict";
// //就表示开启了js的严格模式
// 设置编译后的⽂件是否使⽤严格模式
// 默认值:false
// 案例:
//  "alwaysStrict":true
// 当代码中有引⼊导出模块代码时,js会⾃动进⼊严格模式下

noImplicitAny:不允许隐式的any类型

// 默认值为:false
// 案例:
//  "noImplicitAny":true

strictNullChecks:严格的检查空值

// 默认值为:false
// 案例:
//  "strictNullChecks":false

strict:所有严格检查的总开关

// 默认值为:false
// 案例:
//  "strict":false

TypeScript的语法进阶

配置在直接运⾏ts环境

⾸先全局安装ts-node:npm install -g ts-node

执⾏ts-node命令即可: ts-node hello.ts

面向对象简介

⾯向对象编程:程序之中所有操作都需要通过对象来完成

程序中的对象:

js里面的对象:

  • 内置对象:方法,数组,集合,字符串,number,布尔型
  • 本地对象:window
  • 自建对象,自定义对象

TS中的类

既然要⾯向对象,操作对象,⾸先便要拥有对象,那么下⼀个问题就是如何创建⼀个对象?

要创建⼀个对象,必须先定义⼀个类,所谓的类可以理解为对象模型,程序中可以根据类创建指定类型的对象

1、如何定义类

2、静态修饰符(static):static修饰之后只属于class了,不属于实例对象了

3、readonly :被readonly修饰的属性,只能读取不能修改

//通过class这个关键字来定义⼀个类
class Person{
    name:string;
    age:number;
}


//通过这个类实例化⼀个对象
//let man=new Person();//括号里面没有参数的时候,括号可以省略的
let man=new Person;
man.name="园子";
man.age=30;
console.log(man);


//static
class Animal{
    //name被static修饰之后只属于class了,不属于实例对象了
    static readonly nameD='猫';// 被readonly修饰的属性,只能读取不能修改
    say(){
        console.log("动物在叫");
    }
}

let dog=new Animal;
// dog.name="狗";
// console.log(dog.name);
dog.say();
// Animal.nameD='狗';
// console.log(Animal.nameD);// Cannot assign to 'nameD' because it is a read-only property.

类中的构造方法

1、如何在类中定义⼀个构造⽅法

// 1):定义⼀个简单的构造⽅法
class Dog{
   constructor(){
     console.log("我创建⼀个Dog");
   }
}
const dog=new Dog();
//当我们调 new Dog();的时候我们就等于调⽤Dog中的构造⽅法
//在实例犯法中,this就表示当前的实例
//在构造⽅法中当前对象及时当前新建的那个对象
//可以通过this向新建的对象中添加属性


// 2):定义⼀个有参构造⽅法
class Dog{
   constructor(name:string){
     console.log(name);
   }
}
const dog=new Dog("⼤⻩");
//创建的时候必须传递⼀个string类型的参数

2、this改造构造⽅法

class Animal{
    name:string;
    constructor(name:string){
        //在实例方法中,this就表示当前的实例
        //在构造⽅法中当前对象就是当前新建的那个对象
        //可以通过this向新建的对象中添加属性
        this.name=name;
    }
}

let dog=new Animal("狗");
console.log(dog.name);

继承的简介(extends)

class Animal{
    name:string;
    sleep(){
        console.log(this.name+"在睡觉");
    }
    // 定义一个构造方法来初始化属性,带入一个形参,对上面的name进行赋值
    constructor(name:string){
        this.name=name;
    }
}
// 继承动物类  此时,Animal被称为⽗类,Dog被称为⼦类
class Dog extends Animal{
    hobbit(){
        console.log(this.name+"爱吃骨头");
    }
}

let jm = new Dog("金毛");
jm.hobbit();
console.log(jm.name);
  • 使⽤继承后,⼦类将会拥有⽗类所有的⽅法和属性
  • 通过继承可以将多个类中共有的代码写在⼀个⽗类中
  • 这样只需要写⼀次即可让所有⼦类都同时拥有⽗类中的属性和⽅法
  • 如果希望在⼦类中添加⼀些⽗类中没有的属性或⽅法直接加就⾏

TS中的重写

⼦类覆盖了⽗类中的属性或者是⽅法叫做重写

class Animal{
    name:string="动物";
    sleep(){
        console.log("动物在睡觉");
    }
}

// 对name的重写
class Dog extends Animal{
    name:string="狗";
    sleep(){
        console.log("狗在睡觉");
    }
}

let jm=new Dog();
console.log(jm.name);
jm.sleep();

super关键字

// super  在当前类中  super就表示当前类的父类  如果有参数的话也需要传递对应的参数
class Animal{
    name:string;
    sleep(){
        console.log(this.name+"在睡觉!!!!");
    }
    constructor(name:string){
        this.name=name;
    }
}

class Dog extends Animal{
    // 添加一个属性age
    age:number;
    // 重写sleep方法
    sleep(){
        //super 代表父类   父类也被成为超类
        super.sleep();
    }
    //在子类中定义构造方法的时候,需要通过这个super调用父类的构造方法,
    //因为在子类中定义的构造方法已经把父类的构造方法覆盖了,就不会执行父类的构造方法了
    //所以在父类中定义的属性name就没有办法进行初始化的赋值
    constructor(name:string,age:number){
        super(name);//要写上,否则会覆盖父类的关键字
        this.age=age;
    }
}


let jm=new Dog("金毛",12);
jm.sleep();
console.log(jm);

抽象类(abstract)

以abstract开头的类被称为抽象类

  • 抽象类和其他类区别不⼤,只是不能⽤来创建对象
  • 抽象类就是专⻔⽤来被继承的类
  • 抽象类中可以添加抽象⽅法
  • 抽象⽅法使⽤abstract开头,没有⽅法体
  • 抽象⽅法只能定义在抽象类中,⼦类必须对抽象⽅法进⾏重写
    abstract syaHello():void;
  • 抽象类使⽤场景,当你不希望某个类被创建时,可以使⽤抽象类
abstract class Animal{
    name:string="抽象类";
    // abstract sleep(){}//报错
    // 抽象方法特点
    // 1:没有方法体,没有实现
    abstract sleep():void;
    
}
// let dog=new Animal();//报错
//1:抽象类只能被继承,不能初始化一个实例

//2:子类继承抽象类,必须重写抽象类中所有抽象方法,如果不重写,那么这个类也应该是一个抽像类
// class Dog extends Animal{//报错
//     sleep(){}
// }

//定义一个抽象类不需要重写
abstract class Dogs extends Animal{
   abstract bark():void;
}

class JM extends Dog{
    // 子类继承抽象类,必须重写抽象类中所有抽象方法
    sleep(){}
    bark(){};
}

TS中的接口(interface)

回顾:

type myType=string|number;//类型声明

let a:myType;//说明a只能是字符串类型或者是数字类型
a=123;
// a=true;//报错

接⼝:接⼝⽤来定义⼀个类结构,⽤来定义⼀个类中应该包含哪些属性和⽅法。同时接⼝也可以当成类型声明去使⽤。接⼝可以重复声明,取所有相同接⼝名的并集

//interface+接口名字  包含属性和方法
interface myInterface{
    name:string;
    //1在接口里面的方法都是抽象方法,只有方法名,参数,返回类型,没有返回体的实现
    sleep():void;
}
//2.接口可重复声明
interface myInterface{
    age:number;
}

// 类型声明
let b:myInterface;
b={
    name:'yuanzi',
    age:12, // 上面声明了,下面也要写上去
    sleep(){
        console.log("myInterface");
    }
}
console.log(b.name);//yuanzi
b.sleep();//myInterface


// Person这个类继承了myInterface这个接口  就要继承他的属性和方法
//3.通过一个类来实现接口
class Person implements myInterface{
    name:string;//必须包含前面定义的
    age:number;
    gender:string;
    sleep(){
        console.log(this.name);
    }
    constructor(name:string,age:number,gender){
        this.name=name;
        this.age=age;
        this.gender=gender;
    }
}

let c=new Person('小D',12,'男');
console.log(c);
c.sleep();

快速掌握TS中属性的封装

1、属性修饰符

public: 修饰的属性可以在任意位置访问(修改),是默认值

private: 私有属性,私有属性只能在类内部进⾏访问(修改)-通过在类中添加⽅法使得私有属性可以被 外部访问

protected: 受保护的属性,只能在当前类何当前类的之类中访问(修改)

2、属性封装

class Person {
   private name:string;
   private age:number;
   constructor(name:string,age:number){
       this.name=name;
       this.age=age;
   }
}

3、属性存取器

// getter ⽅法⽤来读取属性
// setter ⽅法⽤来设置属性
//  -它们被称为属性存取器
class Person {
   private name:string;
   private age:number;
   constructor(name:string,age:number){
       this.name=name;
       this.age=age;
   }
   get name():string{
       return this.name;
   }
   set name(name:string):void{
       this.name=name;
   }
}
class Person{
    name:string;
    constructor(name:string){
        this.name=name;
    }
}
let obj=new Person("园子");
obj.name="小D";
console.log(obj.name);//"小D"

class Person{
  name:string;
  private age:number;
    constructor(name:string,age:number){
        this.name=name;
        this.age=age;
    };

    getAge(){
        return this.age;
    }

}
let obj=new Person("园子",20);
// obj.name="小D";
// obj.age=45;
console.log(obj.getAge());
class Person{
    name:string;
    protected  age:number;
    constructor(name:string,age:number){
        this.name=name;
        this.age=age;
    };

   protected getAge(){
        return this.age;
    }

}


class Docker extends Person{
    getAge1(){
        return super.getAge();
    }
}
let obj=new Docker("园子",20);
// obj.name="小D";
// obj.age=45;
console.log(obj.getAge1());
class Person{
    name:string;
   private age:number;
    constructor(name:string,age:number){
        this.name=name;
        this.age=age;
    };

    getAge(){
        return this.age;
    };
    setAge(age:number){
        if(age>=0){
            this.age=age;
        }
    }
 

}

let obj =new Person("园子",26);
// obj.age=30;
obj.setAge(-25);
// obj.age=-30;
console.log(obj.getAge());
class Person{
    name:string;
   private age:number;
    constructor(name:string,age:number){
        this.name=name;
        this.age=age;
    };

    get getAge(){
        return this.age;
    };
    set setAge(age:number){
        if(age>=0){
            this.age=age;
        }

    }
 

}

let obj =new Person("园子",26);
obj.setAge=12;
console.log(obj.getAge);

详解TS中的泛型

泛型使⽤场景:

在定义函数或类时,如果遇到类型不明确就可以使⽤泛型,泛型就是⼀个不确定的类型

传进来是什么类型,传出去就是什么类型

问题:引出

function cache(value:number):number{ 
     return value; 
} 

如何使⽤简单的泛型

function cache<泛型名>(value:泛型名):泛型名{
     return 泛型名;
}

// 定义一个函数  把传入的参数并返回出去 接受一个字符串类型的参数prop  返回的类型也是字符串
function cache(prop:string):string{
    return prop;
}

泛型的约束

// 我们可以指定泛型的类型,如果我们不指定TS解析器会根据我们传递的参数进⾏类型推测
// (建议我们在使⽤泛型的时候指定泛型的类型)
// 使⽤⽅法:
cache<指定泛型类型>('yuanzi');

创建多个泛型

//定义
function cache<泛型名1,泛型名2>(value1:泛型名1,value2:泛型名2):T{
     return T;
}
//调⽤
cache<泛型类型1,泛型类型2>(实参1,实参2);

5、泛型在接⼝中的使⽤




//现在有个需求:实参可能是boolean  string   object  那么如何解决这个问题呢

//any  使用any的话,就会关闭ts的类型检测,不仅影响自己,还会在赋值时关闭其他变量的类型检测
// function cache(prop:any):any{
//     return prop;
// }



// 使用泛型可以解决这个问题
// function cache<泛型名>(value:泛型名):泛型名{
//     return 泛型名;
// }

// function cache<T,P>(prop:T,flag:P):T{
//     return prop;
// }
// let a=cache<string,number>("true",1223);

// 定义了一个泛型接口 myInterface<T>,
// 其中 <T> 表示泛型类型参数,可以是任何类型。
// 接口中包含了一个属性 name,其类型为泛型类型参数 T。
// 这意味着在实现该接口时,可以指定 name 属性的具体类型。
interface myInterface<T>{
    name:T;
}


// 这段代码定义了一个名为 Person 的泛型类实现了 myInterface<T>,
// 同时指定了两个泛型参数 T 和 P。
// 这个类实现了接口 myInterface<T>
// 其中 name 属性的类型是泛型 T,而 age 属性的类型是泛型 P。
// 泛型参数:<T, P> 指定了两个泛型参数 T 和 P,
// 它们可以在创建 Person 类的实例时设定为具体的类型。
class Person<T,P> implements myInterface<T>{
    name:T;// Person 类有一个名为 name 的属性,其类型是泛型参数 T。
    age:P; //Person 类有一个名为 age 的属性,其类型是泛型参数 P。
    // name:T 和 age:P。它们对应 name 和 age 属性,将在构造函数中初始化
    constructor(name:T,age:P){
        this.name=name;
        this.age=age;
    }
}

// 创建实例:当创建 Person 类的实例时,需要提供具体的类型参数以及构造函数参数。
let obj=new Person<string,number>("园子",30);

console.log(obj);

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐