#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;
})();
Однако я не уверен, есть ли способ сделать это без утверждения типа. Добавление пользовательского типа 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
Выглядит хорошо.