Тип «T» является универсальным и может индексироваться только для чтения.ts(2862)

Я пытаюсь написать функцию 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 пусто.

tartget[name] = ... пишет, а не читает. Вы меняете тип аргумента, а это небезопасно с точки зрения типов. Также после этого новое поле все равно не будет доступно: tsplay.dev/NanLpm
jonrsharpe 16.05.2024 15:27

@jonrsharpe да, это сделано намеренно, идея состоит в том, чтобы писать в поля, когда их не существует

yigal 16.05.2024 15:31

@jonrsharpe идея состоит в том, чтобы использовать его вот так typescriptlang.org/play/?#code/…

yigal 16.05.2024 15:34

Тогда вам не хочется что-то вроде tsplay.dev/WzXBQN? Обратите внимание, что на самом деле тип первого аргумента не изменится, чтобы сделать свойство необязательным.

jonrsharpe 16.05.2024 15:38

Комментарий @jonrsharpe верен, он должен написать ответ (или найти объект для обмана), если Игаль согласен, что он полностью отвечает на вопрос.

jcalz 16.05.2024 15:52

Ответы @Nikos Paraskevopoulos и jonrsharpe превосходны и прекрасно решают мой вопрос, большое спасибо!

yigal 16.05.2024 16:45
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
6
671
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Посмотрите это:

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 требует определенной хореографии, чтобы понять, что вы хотите делать с его типами, но в конечном итоге он очень силен.

Другие вопросы по теме