Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript通用接口,其中属性名称和类型为;";_Typescript_Types - Fatal编程技术网

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
的属性相关

不管怎样,呵呵