【问题标题】:Typescript: Nested typings - Looking for a more elegant solutionTypescript: Nested Typings - 寻找更优雅的解决方案
【发布时间】:2021-09-23 15:45:14
【问题描述】:

我正在使用 Typescript Generics 构建 API 抽象,但我正在努力寻找一种优雅的语法来让事情按我的意愿工作。这是我设法开始工作的虚拟版本。关于如何简化事情的任何想法?

interface ExampleInterface {
  LevelOne: {
    LevelTwo: {
      keyOne: string;
      keyTwo: number;
      keyThree: boolean;
    }
  }
}

class ExampleClassOne <T1, K1 extends keyof T1> {
  requestMethod<K2 = 'LevelTwo'> (): Promise<K2 extends keyof T1[K1] ? T1[K1][K2] : any> {
    return new Promise (async (resolve, reject) => {
        try {
            const requestResponse = await axios({
                url: `https://someurl.com/api/`,
                method: 'GET'
            })
            resolve(requestResponse.data)
        } catch (err) {
            reject(err.response.status);
        }
    })
  }
}

class ExampleClassTwo {
  methodObj = {
    levelOne: new ExampleClassOne<ExampleInterface, 'LevelOne'>()
  }
}

尤其是这段代码让我很困扰:

Promise<K2 extends keyof T1[K1] ? T1[K1][K2] : any>

我希望它看起来更像这样:

Promise<T1[K1][K2]>

我仍在努力了解 Typescript,并希望能对这里上演的魔法进行某种解释。为什么二级嵌套需要这个条件类型守卫?

非常感谢。

【问题讨论】:

    标签: typescript generics


    【解决方案1】:

    问题是K2 的约束。在这种情况下没有:

    class ExampleClassOne <T1, K1 extends keyof T1> {
      requestMethod<K2 = 'LevelTwo'> (): Promise<K2 extends keyof T1[K1] ? T1[K1][K2] : any> {
    

    这里的K2 可以是任何类型,因为它不受约束。如果省略,则默认使用"LevelTwo",但它可以是任何字符串、布尔值、对象接口、函数等。

    所以 typescript 注意到您正在尝试通过不保证是该对象的键的类型来索引对象并引发类型错误。这个 sn-p 使用条件类型来处理它,该类型检查以确保 K2 是在使用它钻取 T1[K1] 之前存在的键。


    避免条件的一个好方法是提供更好的约束。这样,条件的一个分支就变成了编译器不允许的类型错误,然后你就不再需要条件了。

    所以要修复它,K2 需要像 K1 一样受到约束,但更深一层。

    class ExampleClassOne <T1, K1 extends keyof T1> {
      requestMethod<K2 extends keyof T1[K1]> (): Promise<T1[K1][K2]> {
    

    Playground

    【讨论】:

    • 我想在requestMethod上具体定义K2"LevelTwo"。这可能吗??
    • 我整理了一个接口树,定义了这个 API 的返回。每个 CRUD 方法都需要并返回模型的不同字段。 LevelOne是主要类型(即联系人),LevelTwo是子类型(即客户),LevelThree是CRUD方法(即更新)。 ExampleClassOne 包含请求方法,ExampleClassTwo 将它们捆绑成类型和子类型。
    • 这样的东西会很好:Promise&lt;T1[K1]['Update']&gt;
    • 抱歉,我不清楚你想要什么。如果T1 是不受约束的,那么你就不能假设它有任何键。
    • T1 & K1 受限于ExampleClassTwo: levelOne: new ExampleClassOne&lt;ExampleInterface, 'LevelOne'&gt;()K2 将始终受限于 ExampleClassOne 中的方法。我想知道我是否应该为K2 使用泛型,因为它将始终被定义?谢谢...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    • 2012-12-01
    • 1970-01-01
    • 2018-04-28
    相关资源
    最近更新 更多