一个ts的最佳练习

我们给这一段程序添加ts

const personWatcher = watchTest({
  firstName: "Saoirse",
  lastName: "Ronan",
  age: 20,
});
personWatcher.on("lastNameChange", (oldValue, newValue) => {});

正常我们添加的ts是这样的 但是这样添加上的ts基本没什么效果

type Watcher = {
  on(name: string, cb: (oldValue: any, newValue: any) => void): void;
};

interface IWatchTest {
  firstName: string;
  lastName: string;
  age: number;
}

declare function watchTest(obj: IWatchTest): Watcher;
const personWatcher = watchTest({
  firstName: "Saoirse",
  lastName: "Ronan",
  age: 20,
});
personWatcher.on("lastNameChange", (oldValue, newValue) => {});

现在我们有个需求

  • 将on后面监听的属性change方法要和传入进来的对象中的键绑定
  • 也就是说我们传入的对象键值为 firstName|lastName|age 我们对应监听的change只能是
  • firstNameChange | lastNameChange | ageChange 如果是xxxChange就会给出报错提示
  • 我们该如何实现呢 思路就是使用联合类型 将上面on里面的name不要只限制为string要让他是传入对象键的联合类型

改造如下:

其中string & keyof T 意思是只取对象键中是字符串的键 过滤掉Symbol等


type Watcher<T> = {
  on(
    name: `${string & keyof T}Change`,
    cb: (oldValue: any, newValue: any) => void
  ): void;
};

interface IWatchTest {
  firstName: string;
  lastName: string;
  age: number;
}

declare function watchTest<T>(obj: T): Watcher<T>;

const personWatcher = watchTest<IWatchTest>({
  firstName: "Saoirse",
  lastName: "Ronan",
  age: 20,
});
personWatcher.on("aaaChange", (oldValue, newValue) => {}); 

aaaChange会报错ageChange编译通过

现在我们已经实现了限制监听方法名字, 现在我又来了一个需求我希望返回回来的oldValue和newValue和我 监听的属性类型是一样的我该怎么办呢

  • 首先 如果要拿到对象的类型我们可以通过T[K]的方式来拿到
  • 我们就可以多定义一个K的泛型 主要限制传入的是对象的键

改造如下:

K extends string & keyof T K必须限制是T中的某个键不能是其他

type Watcher<T> = {
  on<K extends string & keyof T>(
    name: `${string & keyof T}Change`,
    cb: (oldValue: T[K], newValue: T[K]) => void
  ): void;
};

interface IWatchTest {
  firstName: string;
  lastName: string;
  age: number;
}

declare function watchTest<T>(obj: T): Watcher<T>;

const personWatcher = watchTest<IWatchTest>({
  firstName: "Saoirse",
  lastName: "Ronan",
  age: 20,
});
personWatcher.on<"age">("ageChange", (oldValue, newValue) => {});

这样看起来就舒服多了 也能很方便的拿到返回的类型

接下来我想在做一层限制就是我想让我的泛型K和on绑定的属性名称也关联上,因为我现在的代码如果这样写

personWatcher.on<"lastName">("ageChange", (oldValue, newValue) => {});

他是不会提示你报错的文章来源地址https://uudwc.com/A/dMvmx

那么我们该如何关联和 很简单把name后面定义为K就可以了

完整版

type Watcher<T> = {
  on<K extends string & keyof T>(
    name: `${K}Change`,
    cb: (oldValue: T[K], newValue: T[K]) => void
  ): void;
};

interface IWatchTest {
  firstName: string;
  lastName: string;
  age: number;
}

declare function watchTest<T>(obj: T): Watcher<T>;

const personWatcher = watchTest<IWatchTest>({
  firstName: "Saoirse",
  lastName: "Ronan",
  age: 20,
});
personWatcher.on<"lastName">("lastNameChange", (oldValue, newValue) => {});

原文地址:https://blog.csdn.net/weixin_42201272/article/details/131617325

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

上一篇 2023年07月09日 09:14
下一篇 2023年07月09日 09:16