具有隐式属性类型的 Typescript 泛型

标签 typescript generics types

上下文

我无法确定是否可以对类型中的泛型参数使用隐含值,就像在函数中一样。

假设我有以下接口(interface)定义我的一些数据库表的结构:

interface Tables {
  'table-users': { userId: string, username: string },
  'table-posts': { postId: string, userId: string, title: string },
}

我可以编写一个过于简化的函数,允许我使用以下方式写入这些表:

const write = <T extends keyof Tables>(table: T, item: Tables[T]): boolean => {
  // ... do something
  
  return true;
}

这让我可以做


write('table-users', { userId: '123', username: 'John Doe' }); // ✅
write('table-posts', { postId: 'abc', userId: '123', title: 'First Post' }); // ✅

但不是

write('table-users', { postId: 'abc' }); // ❌
write('table-posts', { userId: 'abc' }); // ❌

到目前为止,还不错。

问题

但是,现在我希望能够构造一个类型(类似于函数),该类型采用需要作为表名的属性,并且该类型中的另一个属性需要具有正确的项目格式。

我认为按照这些思路应该可以工作:

type Item<T extends keyof Tables> = {
  table: T,
  item: Tables[T],
}

并自动允许:

const userItem: Item = {
  table: 'table-users',
  item: {
    userId: '1',
    username: 'John Doe',
  }
};

const postItem: Item = {
  table: 'table-posts',
  item: {
    postId: '123',
    userId: '1',
    username: 'John Doe',
  }
};

或者只是使用 Item 作为函数参数类型提示,但它没有,因为它总是需要显式定义表名:

const userItem: Item<'table-users'> = {
  table: 'table-users',
  item: {
    userId: '1',
    username: 'John Doe',
  }
};

const postItem: Item<'table-posts'> = {
  table: 'table-posts',
  item: {
    postId: '123',
    userId: '1',
    title: 'First Post',
  }
};

任何线索是否可以在 TypeScript 中找到我正在寻找的东西?我认为它应该是,因为它可能是,我可能只是在做一些愚蠢的事情,但我似乎无法修复它。

编辑

相比之下,这个有效的:

type Item = {
  [T in keyof Tables]?: {
    item: Tables[T]
  }
}

但我希望做同样的事情,但使用 T 作为值,而不是键。

最佳答案

您可以使用 conditional types像这样:

type ItemGeneric<T> = T extends keyof Tables ? {
    table: T;
    item: Tables[T];
} : never;

type Item = ItemGeneric<keyof Tables>;

这将根据您为 table 设置的字符串值隐式设置 item 的类型。 Here's a small demo这在行动中。

全部归功于nmain on github感谢您告诉我这件事。

关于具有隐式属性类型的 Typescript 泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65982905/

相关文章:

TypeScript 编译错误无法调用类型缺少调用签名的表达式

java - 在泛型类中使用类的子类型

javascript - 使用字符串列表测试字符串

html - Angular:重新渲染图像标签中的异步数据

javascript - 强制 typescript 不删除未使用的引用

javascript - TypeScript:TypedArray 的泛型类型定义

django - 如何在 Django 中创建和强制执行通用的 OneToOne 关系?

types - Idris 中的 View - Idris 书中类型驱动开发的 list 10.5

python - 我可以添加属性的最通用的 python 类型是什么?

python - 在 Python 中创建真正的空类型