Typescript: как использовать универсальный параметр в качестве ключа объекта - PullRequest
1 голос
/ 03 июня 2019

Можно ли написать интерфейс, который принимает строковую константу в качестве одного из своих параметров и использует ее в качестве ключа объекта?

Например, предполагая, что я делаю два разных запроса GraphQL, оба изкоторые возвращают User, но под разными именами ключей:

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

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

Я думаю, что написание универсального интерфейса будет выглядеть примерно так:

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

interface User {
    username: string
    id: string
}

type UserByIdResponse = GraphQLResponse<'userById', User>
type UserByUsernameResponse = GraphQLResponse<'userByUsername', User>

Но, этоне работает .

1 Ответ

2 голосов
/ 03 июня 2019

Ты рядом. Это относится к категории Mapped Types . Вам нужно сделать два изменения:

  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>;

Пример использования

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'
        }
    }
}
...