Как я могу использовать массивы со свойствами объекта в typescript

#arrays #typescript #javascript-objects

Вопрос:

Есть ли способ использовать массивы со свойствами объекта без использования @ts-ignore в typescript

Допустим, у меня есть эта функция, она пытается преобразовать массив в массив со свойством prop. Это работает нормально, за исключением того факта, что они являются @ts-ignore

     const addPropToArray = <T extends unknown>(x: T[]): T[] amp; {prop: number} => {
      //@ts-ignore
      const y: T[] amp; {prop: number} = [...x];
      y.prop = 3;
      return y
    };
 

Очевидно, я не могу этого сделать

 const x: string[] amp; {prop:number} = // what could go here
 

само по себе, поэтому я думал об использовании функции, но даже тогда функция должна иметь @ts-ignore .

Являются ли массивы со свойствами объекта настолько плохой идеей, что typescript не пытается их хорошо поддерживать, или мне чего-то не хватает?

Может быть, это какая-то вариация этого, которая может сработать?

 const x: string[] amp; {prop:number} = {...["a","b","c"], prop: 4}
 

очевидно, что проблема здесь в том, что это больше не массив.

РЕДАКТИРОВАТЬ: я понимаю, что мог бы просто привести значение вместо использования @ts-ignore , но этот порог не кажется лучшим решением

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

1. «Являются ли массивы со свойствами объекта просто такой плохой идеей ..» ^_^ (Если сохранить, что массивы отличаются от массивоподобных объектов с дополнительными свойствами объекта ..)

2. @jcalz не могли бы вы ответить на мой вопрос с демонстрацией того, что вы имеете в виду?

3. Я могу, когда в следующий раз перейду на другое устройство, не связанное с телефоном.

4. Object.assign Кстати, Oh будет работать, но распространение не будет. Это выглядело бы Object.assign([...x], {prop: 3}) так, но на данный момент я не могу проверить это на точность

5. Вот так . Все еще нет времени, чтобы написать ответ, но это, по крайней мере, работает.

Ответ №1:

Очевидно, я не могу этого сделать const x: string[] amp; {prop:number} = // what could go here

Вы могли бы сделать это, если присвоите возвращаемое значение самоисполняющейся анонимной функции. Что-то вроде этого, например:

 interface ArrayProps {
    prop: number;
}

const x: string[] amp; ArrayProps = (() => {
    const xPartial: string[] amp; Partial<ArrayProps> = [];
    xPartial.prop = 3;

    return xPartial as string[] amp; ArrayProps;
})();
 

Игровая площадка TypeScript

Однако я не уверен, есть ли способ сделать это без утверждения типа. Добавление пользовательского типа guard вместо утверждения типа потребует учета пути, по которому происходит сбой типа guard, поэтому x в конечном итоге также может быть undefined или что-то в зависимости от того, как обрабатывается этот путь.

Ответ №2:

Object.assign(target, source) Метод копирует перечисляемые собственные свойства из source объекта в target объект и возвращает дополненные target . И типизация стандартной библиотеки TypeScript для этого метода выглядит следующим образом:

 interface ObjectConstructor {
    assign<T, U>(target: T, source: U): T amp; U;
}
 

Это означает, что он моделирует операцию как производящую пересечение типов source и оригинала target , что является именно тем, что вы ищете!

Итак, вы можете написать addPropToArray() так:

 const addPropToArray = <T extends unknown>(x: T[]): T[] amp; { prop: number } => {
  return Object.assign([...x], { prop: 3 });
};
 

без утверждений типа или //@ts-ignore комментариев.

Обратите внимание, что если вам когда-нибудь придется выбирать между утверждениями типа и //@ts-ignore , выберите утверждения типа. Они оба имеют возможность останавливать ошибки, и ни один из них не является безопасным. Но утверждения типа ограничены по объему и сообщают компилятору обрабатывать определенное значение, как если бы оно было определенного типа, в то время //@ts-ignore как просто подавляет сообщение об ошибке и может иметь странные нелокальные побочные эффекты. Использование утверждения типа похоже на нажатие кнопки «временное отключение» на вашем детекторе дыма, чтобы вы могли спокойно готовить ужин, в то время как использование //@ts-ignore похоже на полное удаление батареи детектора дыма.


В любом случае, давайте убедимся, что это работает:

 const z = addPropToArray(["a", "b"]);
console.log(z) // ["a", "b"]
console.log(z.prop) // 3
 

Выглядит хорошо.

Ссылка на игровую площадку для кода