Typescript通用接口,其中属性名称和类型为;";
我有一个用例,外部查询返回一个对象,该对象的属性与我的一个接口同名。正如您在示例Typescript通用接口,其中属性名称和类型为;";,typescript,types,Typescript,Types,我有一个用例,外部查询返回一个对象,该对象的属性与我的一个接口同名。正如您在示例executeQuery函数中所看到的,如果我将“message”作为查询传入,那么将返回一个名为“message”的具有1个属性的对象 我希望能够创建一个T的通用接口,该接口有1个属性,其中名称是T的名称,类型是T 我知道有运行时解决方案,但我想知道在编译时是否可以只使用Typescript类型 共享代码: function executeQuery<T>(query: "message" | "mai
executeQuery
函数中所看到的,如果我将“message”作为查询传入,那么将返回一个名为“message”的具有1个属性的对象
我希望能够创建一个T
的通用接口,该接口有1个属性,其中名称是T
的名称,类型是T
我知道有运行时解决方案,但我想知道在编译时是否可以只使用Typescript类型
共享代码:
function executeQuery<T>(query: "message" | "mailbox") {
const data = query === "message" ?
{ Message: { id: 1 } } as unknown as T :
{ Mailbox: { id: 2 } } as unknown as T
return { data: data }
}
interface Message {
id: number
}
interface Mailbox {
id: number
}
函数执行(查询:“消息”|“邮箱”){
常量数据=查询==“消息”?
{消息:{id:1}}与T一样未知:
{邮箱:{id:2}}与T一样未知
返回{data:data}
}
接口消息{
身份证号码
}
接口邮箱{
身份证号码
}
第一种解决方案:
interface AllContainer {
Message: Message
Mailbox: Mailbox
}
const messageQueryResult = executeQuery<AllContainer>("message")
console.log(messageQueryResult.data.Message.id)
const mailboxQueryResult = executeQuery<AllContainer>("mailbox")
console.log(mailboxQueryResult.data.Mailbox.id)
interface MessageContainer {
Message: Message
}
interface MailboxContainer {
Mailbox: Mailbox
}
const messageQueryResult2 = executeQuery<MessageContainer>("message")
console.log(messageQueryResult2.data.Message.id)
const mailboxQueryResult2 = executeQuery<MailboxContainer>("mailbox")
console.log(mailboxQueryResult2.data.Mailbox.id)
接口所有容器{
信息:信息
邮箱:邮箱
}
const messageQueryResult=executeQuery(“消息”)
console.log(messageQueryResult.data.Message.id)
const mailboxQueryResult=executeQuery(“邮箱”)
console.log(mailboxQueryResult.data.Mailbox.id)
第二种解决方案:
interface AllContainer {
Message: Message
Mailbox: Mailbox
}
const messageQueryResult = executeQuery<AllContainer>("message")
console.log(messageQueryResult.data.Message.id)
const mailboxQueryResult = executeQuery<AllContainer>("mailbox")
console.log(mailboxQueryResult.data.Mailbox.id)
interface MessageContainer {
Message: Message
}
interface MailboxContainer {
Mailbox: Mailbox
}
const messageQueryResult2 = executeQuery<MessageContainer>("message")
console.log(messageQueryResult2.data.Message.id)
const mailboxQueryResult2 = executeQuery<MailboxContainer>("mailbox")
console.log(mailboxQueryResult2.data.Mailbox.id)
接口消息容器{
信息:信息
}
接口MailboxContainer{
邮箱:邮箱
}
const messageQueryResult2=执行任务(“消息”)
console.log(messageQueryResult2.data.Message.id)
const mailboxQueryResult2=执行任务(“邮箱”)
console.log(mailboxQueryResult2.data.Mailbox.id)
我希望能够做到的是:
interface GenericContainer<T> {
[T.Name]: T // invalid Typescript
}
const messageQueryResult3 = executeQuery<GenericContainer<Message>>("message")
console.log(messageQueryResult3.data.Message.id)
const mailboxQueryResult3 = executeQuery<GenericContainer<Mailbox>>("mailbox")
console.log(mailboxQueryResult3.data.Mailbox.id)
接口通用容器{
[T.Name]:T//类型脚本无效
}
const messageQueryResult3=执行任务(“消息”)
console.log(messageQueryResult3.data.Message.id)
const mailboxQueryResult3=执行任务(“邮箱”)
console.log(mailboxQueryResult3.data.Mailbox.id)
首先,我将为消息
和邮箱
类型添加一些区别属性。TypeScript的类型系统并不是名义上的,所以如果两个代码< >消息< /代码>和<代码>邮箱具有相同的精确结构,编译器将考虑它们相同的类型,尽管它们的名称不同。因此,让我们这样做是为了避免潜在的问题:
interface Message {
id: number,
message: string; // adding distinct property
}
interface Mailbox {
id: number,
mailbox: string; // distrinct property
}
因为类型系统不是名义上的,所以它实际上并不关心您为类型或接口指定的名称。因此,即使在编译时,编译器也无法提供任何句柄来提取接口的名称
如果您正在寻找编译时解决方案,您将不得不重构一些东西。忽略类型名称,但不忽略对象的键名称(因为属性键在运行时存在,并且具有不同键的两种类型实际上是不同的类型)。因此,您可以从一个类似于AllContainer
的类型开始:
interface AllContainer {
Message: {
id: number,
message: string;
}
Mailbox: {
id: number,
mailbox: string;
}
}
而不是将该类型称为Message
,而是将其称为AllContainer[“Message”]
。您可以更进一步、更强烈地键入executeQuery()
函数,为调用者提供更好的类型推断(同时在实现中仍然需要类型断言):
接口查询映射{
信息:“信息”,
邮箱:“邮箱”
}
函数执行(查询:K){
常量数据=(查询==“消息”?
{消息:{id:1}}:
{Mailbox:{id:2}})与Pick一样
返回{data:data}
}
const messageQueryResult=executeQuery(“消息”)
console.log(messageQueryResult.data.Message.id)
const mailboxQueryResult=executeQuery(“邮箱”)
console.log(mailboxQueryResult.data.Mailbox.id)
所有这些都是编译的。。。QueryMap
接口为编译器提供了一个句柄,说明executeQuery()
的参数如何与您要讨论的AllContainer
的属性相关
无论如何,希望这能让你对如何进行有所了解。祝你好运 首先,我将为
消息
和邮箱
类型添加一些区别属性。TypeScript的类型系统并不是名义上的,所以如果两个代码< >消息< /代码>和<代码>邮箱具有相同的精确结构,编译器将考虑它们相同的类型,尽管它们的名称不同。因此,让我们这样做是为了避免潜在的问题:
interface Message {
id: number,
message: string; // adding distinct property
}
interface Mailbox {
id: number,
mailbox: string; // distrinct property
}
因为类型系统不是名义上的,所以它实际上并不关心您为类型或接口指定的名称。因此,即使在编译时,编译器也无法提供任何句柄来提取接口的名称
如果您正在寻找编译时解决方案,您将不得不重构一些东西。忽略类型名称,但不忽略对象的键名称(因为属性键在运行时存在,并且具有不同键的两种类型实际上是不同的类型)。因此,您可以从一个类似于AllContainer
的类型开始:
interface AllContainer {
Message: {
id: number,
message: string;
}
Mailbox: {
id: number,
mailbox: string;
}
}
而不是将该类型称为Message
,而是将其称为AllContainer[“Message”]
。您可以更进一步、更强烈地键入executeQuery()
函数,为调用者提供更好的类型推断(同时在实现中仍然需要类型断言):
接口查询映射{
信息:“信息”,
邮箱:“邮箱”
}
函数执行(查询:K){
常量数据=(查询==“消息”?
{消息:{id:1}}:
{Mailbox:{id:2}})与Pick一样
返回{data:data}
}
const messageQueryResult=executeQuery(“消息”)
console.log(messageQueryResult.data.Message.id)
const mailboxQueryResult=executeQuery(“邮箱”)
console.log(mailboxQueryResult.data.Mailbox.id)
所有这些都是编译的。。。QueryMap
接口为编译器提供了一个句柄,说明executeQuery()
的参数如何与您要讨论的AllContainer
的属性相关
不管怎样,呵呵