Я пытаюсь написать функцию TypeScript для создания полей по требованию. Вот что есть на данный момент:
export function lazy_field<T extends Record<string,unknown>,FIELD>(
target:T,
name:string,
init:()=>FIELD
){
const exists=target[name]
if (exists!==undefined)
return exists
const new_val=init()
target[name]=new_val
return new_val
}
Моя проблема в том, что в строке target[name]=new_val есть ошибка:
Type 'T' is generic and can only be indexed for reading.ts(2862)
Что это за ошибка и как ее исправить? tsconfig.json пусто.
@jonrsharpe да, это сделано намеренно, идея состоит в том, чтобы писать в поля, когда их не существует
@jonrsharpe идея состоит в том, чтобы использовать его вот так typescriptlang.org/play/?#code/…
Тогда вам не хочется что-то вроде tsplay.dev/WzXBQN? Обратите внимание, что на самом деле тип первого аргумента не изменится, чтобы сделать свойство необязательным.
Комментарий @jonrsharpe верен, он должен написать ответ (или найти объект для обмана), если Игаль согласен, что он полностью отвечает на вопрос.
Ответы @Nikos Paraskevopoulos и jonrsharpe превосходны и прекрасно решают мой вопрос, большое спасибо!






Посмотрите это:
export function lazy_field<T, K extends keyof T, FIELD extends T[K]>(
target: T,
name: K,
init: ()=>FIELD
){
const exists=target[name]
if (exists!==undefined)
return exists
const new_val=init()
target[name]=new_val
return new_val
}
Грубо говоря, это говорит: «Для типа T, где K — ключ этого типа, а FIELD — это тип T[K]». Ваш пример с игровой площадкой, похоже, работает с этим. Иногда Typescript требует определенной хореографии, чтобы понять, что вы хотите делать с его типами, но в конечном итоге он очень силен.
tartget[name] = ...пишет, а не читает. Вы меняете тип аргумента, а это небезопасно с точки зрения типов. Также после этого новое поле все равно не будет доступно: tsplay.dev/NanLpm