打字稿:如何使用泛型参数作为对象键

Goo*_*dea 14 typescript typescript-generics

是否可以编写一个接受字符串常量作为其参数之一的接口,并将其用作对象的键?

例如,假设我发出两个不同的 GraphQL 请求,它们都返回 a User,但键名不同:

const userByIdResult = {
  data: {
    userById: {
       id: 123,
       username: 'joseph'
    }
  }
}

const userByUsernameResult = {
  data: {
    userByUsername: {
       id: 123,
       username: 'joseph'
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我想写一个通用接口会是这样的:

interface GraphQLResponse<QueryKey, ResponseType> {
  data: {
    [QueryKey]: ResponseType
  }
}

interface User {
    username: string
    id: string
}

type UserByIdResponse = GraphQLResponse<'userById', User>
type UserByUsernameResponse = GraphQLResponse<'userByUsername', User>
Run Code Online (Sandbox Code Playgroud)

但是,这行不通

Sha*_*tin 25

你很接近。这属于映射类型类别。您需要进行两项更改:

  1. QueryKey extends string
  2. key in QueryKey
interface GraphQLResponse<QueryKey extends string, ResponseType> {
    data: {
        [key in QueryKey]: ResponseType;
    }
}

interface User {
    username: string;
    id: number;
}

type UserByIdResponse = GraphQLResponse<'userById', User>;
type UserByUsernameResponse = GraphQLResponse<'userByUsername', User>;
Run Code Online (Sandbox Code Playgroud)

示例用法

const userByIdResult: UserByIdResponse = {
    data: {
        userById: {
            id: 123,
            username: 'joseph'
        }
    }
}

const userByUsernameResult: UserByUsernameResponse = {
    data: {
        userByUsername: {
            id: 123,
            username: 'joseph'
        }
    }
}

const userByIdResultBoom: UserByIdResponse = {
    data: {
        userByUsername: {
            id: 123,
            username: 'joseph'
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的好解释!我对此完全感到困惑,因为“[key in x]”听起来像是在循环数组,所以我有点困惑。 (3认同)