Как использовать Typescript generics для создания функции, которая может использоваться на похожих объектах?

#typescript #types

#typescript #типы

Вопрос:

У меня есть два типа, которые разделяют подмножество свойств, например

 type A = {
  x: number
  y: number
  desc: string
}

type B = {
  x: number
  y: number
  address: number
}
  

Я хотел бы иметь только одну функцию, которая может что-то делать с этими типами, читая только некоторые реквизиты:

 const munge = <T>(list: T[]): T[] => list.sort((a,b) => a.x - b.x)
  

Очевидно, что это не работает (ошибка Property 'x' does not exist on type 'T'. ), даже если я пытаюсь использовать munge на A[] (таким образом, я узнаю, что обобщения не работают как шаблоны C ).

Я понимаю, что это может быть ограничением языка, но что я вообще могу здесь сделать? Должен ли я специально определять munge в терминах типов A и B или какого-либо другого типа, который является их подмножеством? Дело в том, что я хотел бы иметь возвращаемый тип be T[] , то есть, если я отправлю в B[] to munge , я бы хотел, чтобы typescript понимал, что munge в этом случае вернет обратно a B[] . Казалось бы, если я munge явно определю, чтобы принять A или B (или его пока еще неписаный базовый тип C , имеющий только x prop), позже будет больше уродства при приведении его обратно к любому типу, в который он вошел munge как.

Например, было бы неприемлемо, чтобы мне нужно было написать две реализации munge , одну taking A[] и одну taking B[] . Правда ли, что это единственный практичный чистый способ сделать это? (это не чисто)

Ответ №1:

Пока этот код кажется достаточно простым для чтения и выполняет свою работу. Хотя мне это не нравится.

 type A = {
  x: number;
  desc: string;
};
type B = {
  x: number;
  addr: number;
};
type C = {
  x: number;
};

const munge = <T extends C>(list: T[]): T[] => list.sort((a, b) => a.x - b.x);

const aa: A[] = [
  { x: 5, desc: "a" },
  { x: 0, desc: "" },
];

console.log(aa);
const z = munge(aa);
// editor shows type of z is A[]. I'm satisfied...
console.log(z);
  

Комментарии:

1. Это ответ. Структурная типизация может быть не слишком удобной для тех, кто использует более жесткую систему типов, но это естественный способ выразить это в TS.