Типы ключей и значений в TypeScript - PullRequest
0 голосов
/ 01 ноября 2018
interface A { a?: number };
interface B { a?: string };

function copy<
    Source extends object,
    Destination extends { [destinationKey in keyof Source]?: (1) }
>(
    source: Source,
    key: keyof Source,
    destination: Destination,
    transformer: (value: (2)) => (3) 
) {
    if (source[key] !== undefined) {
        destination[key] = transformer ? transformer(source[key]) : source[key];
    }
}

const a: A = { a: 123 };
const b: B = {};

copy(a, "a", b, (value) => value.toString());

В приведенном выше примере, что я могу использовать для следующих заполнителей:

  • (1) - тип значения в Destination, связанный с соответствующим ключом в Source.
  • (2) - тип значения в Source, связанный с ключом, указанным параметром key.
  • (3) - тип значения в Destination, связанный с ключом, указанным параметром key.

1 Ответ

0 голосов
/ 01 ноября 2018

Вам необходим дополнительный параметр типа, представляющий фактический ключ, который будет передан. Этот параметр будет выведен в виде строкового литерала на основе значения, переданного параметру key. С этим новым типом мы можем использовать запросы типа, чтобы получить конкретное свойство типа в типах Source и Destination.

Также, поскольку мы заботимся только о конкретном ключе K, мы можем использовать его, когда мы определили тип Destination как имеющий его (вместо указания, что Destination должен иметь все ключи Source). Так как нам на самом деле не важен тип свойства назначения, только то, что оно существует и что функция transformer должна возвращать значение того же типа, что и это свойство, мы можем просто указать тип свойства в Destination как unknown.

interface A { a?: number };
interface B { a?: string };

function copy<
    K extends keyof Source, // The extra type parameter
    Source extends object,
    Destination extends { [destinationKey in K]?: unknown } // Can be anything we don't really care, we only care about the K key existing
>(
    source: Source,
    key: K, // The key is of type K
    destination: Destination,
    transformer: (value: Source[K]) => Destination[K] // We use K to specify the relation between Source and Destination property type
) {
    if (source[key] !== undefined) {
        destination[key] = transformer ? transformer(source[key]) : source[key];
    }
}

const a: A = { a: 123 };
const b: B = {};

copy(a, "a", b, (value) => value.toString());
copy(a, "a", b, (value) => value); /// error
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...