ArkTS的进阶语法-1(泛型,工具类型,空安全)

ArkTS的进阶语法

(今天更新的是泛型,工具类型,空安全)

1. 泛型🎈

​ 泛型在保证类型安全(不丢失类型信息)的同时,可以让函数等与多种不同的类型一起工作,灵活可复用

**通俗一点就是:类型是可变的!

1.泛型函数

顾名思义就是,泛型和函数结合到一起使用

Type 是泛型参数的名字,类似于之前的形参,

  • 可以自行定义,有意义即可

  • 首字母大写

  • 参见泛型参数名 T、Type

    php 复制代码
    // 函数定义
    function identity<Type>(arg: Type): Type {
      return arg;
    }
    
    // 在使用的时候传入具体的类型,函数就可以正常工作啦~
    identity<string>('123')
    identity<number>(123)
    identity<boolean>(false)
    identity<string[]>(['1', '2', '3'])

    结合 编译器 的 类型推断 功能,在使用函数的时候还可以进行简写,比如下面的写法,和上面的是一样的。

    虽然大部分时候可以推断出类型,但是如果碰到 编译器 无法推断类型时,就需要显式传入类型参数,这在更复杂的示例中可能会发生。

sql 复制代码
identity('123')
identity(123)
identity(false)
identity(['1', '2', '3'])

使用泛型变量

类型变量可以用在任意支持的位置,实现更为复杂的功能

csharp 复制代码
//将类型变量 Type,作为数组项的类型即可
function identity<Type>(arr: Type[]): number {
  return arr.length
}

2.使用泛型约束

如果开发中不希望任意的类型都可以传递给 **类型参数 ,**就可以通过泛型约束来完成

核心步骤:

  1. 定义用来约束的 接口(interface)

  2. 类型参数通过 extends 即可实现约束

    typescript 复制代码
    interface 接口{
      属性:类型
    }
    function 函数<Type extends 接口>(){}
    
    // 后续使用函数时,传入的类型必须要有 接口中的属性
    ------试一试
    interface ILengthwise {
      length: number
    }
    
    function identity<Type extends ILengthwise>(arr: Type) {
      console.log(arr.length.toString())
    }
    
    // 使用的时候 只要有 length 属性即可
    identity([1, 2, 3, 4]) // 数组有 length 属性 正常运行
    identity('1234') // 字符串也有 length 属性 正常运行
    
    // identity(124) // 数值没有 length 属性 报错
    
    class Cloth implements ILengthwise {
      length: number = 10
    }
    
    class Trousers {
      length: number = 110
    }
    
    identity(new Cloth()) // Cloth 有 length 属性 正常运行
    identity(new Trousers()) // Trousers 有 length 属性 正常运行

3.多个泛型参数

日常开发的时候,如果有需要可以添加多个 类型变量,只需要定义并使用 多个类型变量即可

typescript 复制代码
function funcA<T, T2>(param1: T, param2: T2) {
  console.log('参数 1', param1)
  console.log('参数 2', param2)
}

funcA<string, number>('张三', 18)
funcA<string[], boolean[]>(['张三','李四'], [false])

4.泛型接口

定义接口时结合泛型,那么这个接口就是 泛型接口

typescript 复制代码
interface 接口<Type>{
  // 内部使用Type
}
interface IdFunc<Type> {
  id: (value: Type) => Type
  ids: () => Type[]
}

let obj: IdFunc<number> = {
  id(value) { return value },
  ids() { return [1, 3, 5] }
}

5.泛型类

和泛型接口类似,如果定义类的时候结合泛型,那么这个类就是 泛型类

csharp 复制代码
class 类名<Type>{
  // 内部可以使用 Type
}
-----试一试
// 定义
class Person <T> {
  id: T

  constructor(id: T) {
    this.id = id
  }

  getId(): T {
    return this.id
  }
}

// 使用
let p = new Person<number>(10)

2.工具类型🎈

ArkTS提供了4 中工具类型,来帮组我们简化编码

4 种工具类型中,熟练掌握 Partial 即可,可以简化编码

1.partial

(partial:部分)

基于传入的Type类型构造一个[新类型],将Type的所有属性设置为可选。

(泛型约束太复杂了这个完全可以替代他)

typescript 复制代码
type 新类型 = Partial<接口>
type 新类型 = Partial<类>

// 后续使用新类型即可
interface Person {
  name: string 
  age: number 
  friends: string[]
}

type ParPerson = Partial<Person>

// 因为都是可选的,可以设置为空对象
let p: ParPerson = {}

2.Required

基于传入的Type类型构造一个【新类型】,将 Type 的所有属性设置为必填

typescript 复制代码
type 新类型 = Required<接口>
type 新类型 = Required<类>

// 后续使用新类型即可
class Person {
  name?: string
  age?: number
  friends?: string[]
}

type RequiredPerson = Required<Person>

// 都是必须得属性,必须设置值
let p: Required<Person> = {
  name: 'jack',
  age: 10,
  friends: []
}

3.Readonly

基于 Type构造一个【新类型】,并将Type 的所有属性设置为readonly

ini 复制代码
type 新类型 = Readonly<接口>
type 新类型 = Readonly<类>

// 后续使用新类型即可
class Person {
  name: string = ''
  age: number = 0
}

type ReadonlyIPerson = Readonly<Person>

const p: ReadonlyIPerson = {
  name: 'jack',
  age: 10
}

p.name = 'rose' // 报错 属性全部变成只读

4.Record<Keys,Type>

构造一个对象类型,其属性键为Keys,属性值为Type。该实用程序可用于将一种类型的属性映射到另一种类型。

typescript 复制代码
class CatInfo {
  age: number = 0
  breed: string = ''
}

// 联合类型
type CatName = "miffy" | "boris" | "mordred";

// 通过Record 构建新的对象类型
// 属性名:必须是CatName 中的值
// 属性值:必须是CatInfo 类型
type Ctype = Record<CatName, CatInfo>

const cats: Ctype = {
  'miffy': { age: 5, breed: "Maine Coon" },
  'boris': { age: 5, breed: "Maine Coon" },
  'mordred': { age: 16, breed: "British Shorthair" },
};

3.空安全🎈

默认情况下,ArkTS中的所有类型都是不可为空的。如果要设置为空,需要进行特殊的处理,并且在获取 可能为空的值的时候也需要特殊处理

1.联合类型设置为空

typescript 复制代码
let x: number = null;    // 编译时错误
let y: string = null;    // 编译时错误
let z: number[] = null;  // 编译时错误
通过联合类型指定为空即可,使用时可能需要判断是否为空
// 通过联合类型设置为空
let x: number | null = null;
x = 1;    // ok
x = null; // ok
// 取值的时候,根据需求可能需要考虑 屏蔽掉空值的情况
if (x != null) { /* do something */ }

2.非空断言运算符

后缀运算符! 可用于断言其操作数为非空。

应用于空值时,运算符将抛出错误。否则,值的类型将从T | null更改为T:

ini 复制代码
let x: number | null = 1;
let y: number
y = x + 1;  // 编译时错误:无法对可空值作加法
y = x! + 1; // 通过非空断言,告诉编译器 x不为 null

3.空值合并运算符

空值合并二元运算符?? 用于检查左侧表达式的求值是否等于null。如果是,则表达式的结果为右侧表达式;否则,结果为左侧表达式。

换句话说,a ?? b等价于三元运算符a != null ? a : b。

在以下示例中,getNick方法如果设置了昵称,则返回昵称;否则,返回空字符串:

csharp 复制代码
class Person {
  name: string | null = null

  getName(): string {
    // return this.name === null ? '' : this.name
    // 等同于 如果 name不为空 就返回 name 反之返回 ''
    return this.name ?? ''
  }
}

4.可选链

在访问对象属性时,如果该属性是undefined或者null,可选链运算符会返回undefined。

(可选链?当前面的对象不为空或undefined才调用属性或方法)

ts 复制代码
class Dog {
  bark() {
    console.log('啊呜~')
  }
}

class Person {
  name?: string
  dog?: Dog

  constructor(name: string, dog?: Dog) {
    this.name = name
    this.dog = dog
  }
}

const p: Person = new Person('jack')

// p.dog.bark()// 报错 dog 可能为空

// 逻辑判断
if (p.dog) {
  p.dog.bark()
}

// 当 dog不为null 或 undefined 时 再调用 bark 并且不会报错
p.dog?.bark()

---------------------------------------感觉写的不错的话就点点关注吧😘❤❤❤----------------------------------------------

相关推荐
不是吧这都有重名18 分钟前
利用systemd启动部署在服务器上的web应用
运维·服务器·前端
霸王蟹19 分钟前
React中巧妙使用异步组件Suspense优化页面性能。
前端·笔记·学习·react.js·前端框架
Maỿbe28 分钟前
利用html制作简历网页和求职信息网页
前端·html
森叶1 小时前
Electron 主进程中使用Worker来创建不同间隔的定时器实现过程
前端·javascript·electron
霸王蟹1 小时前
React 19 中的useRef得到了进一步加强。
前端·javascript·笔记·学习·react.js·ts
霸王蟹1 小时前
React 19版本refs也支持清理函数了。
前端·javascript·笔记·react.js·前端框架·ts
繁依Fanyi1 小时前
ColorAid —— 一个面向设计师的色盲模拟工具开发记
开发语言·前端·vue.js·编辑器·codebuddy首席试玩官
明似水2 小时前
Flutter 开发入门:从一个简单的计数器应用开始
前端·javascript·flutter
周胡杰2 小时前
组件导航 (Navigation)+flutter项目搭建-混合开发+分栏
数码相机·flutter·华为·电脑·harmonyos·鸿蒙
沐土Arvin2 小时前
前端图片上传组件实战:从动态销毁Input到全屏预览的全功能实现
开发语言·前端·javascript