Задать вопрос
Fragster
@Fragster
помогло? отметь решением!

Как типизировать массив объектов props так, чтобы он знал, что в объекте есть ключ, имя которого передается в другом prop?

Сейчас нет ругани так:
const props = defineProps({
  options: {
// определение массива Record<string,string>, из-за того, что ниже идет el[props.optionLabel]?.toLowerCase(), 
// можно как-то сделать так, чтобы это был не Record, а тип объекта с двумя динамическими ключами, 
// одно - строка, другое - произвольного типа, по дефолту - {label: string, value: unknown}?
    type: Array as PropType<Record<string,string>[]>,
    required: true
  },
  optionLabel: {
    type: String,
    default: 'label'
  },
  optionValue: {
    type: String,
    default: 'value'
  }
})

const filter = ref('')

const filteredOptions = computed(() => {
  const tmp = filter.value.toLowerCase()
  if (tmp === '') return props.options
// вот тут ругается на возможный undefined, если убрать "as string", оно и понятно. 
// Можно как-то убрать декларацией типов, чтобы оно также падало, если в props кривота?
// Если просто убрать - то ругается на возможный undefined и требует "?", после чего перестает падать в тестах
  return props.options.filter((el) => (el[props.optionLabel] as string).toLowerCase().includes(tmp)) 
})


есть что-то в документации, что может помочь: https://vuejs.org/api/sfc-script-setup.html#type-o... но я пока не смог разобраться в TS настолько, чтобы реализовать то, что хочу.

UPD

С помощью генерика получилось сделать так, осталось два костыля:
<script setup lang="ts" generic="T extends {[propName: string]: unknown}">
import { computed, ref } from 'vue'

type keyofString = { [k in keyof T]: T[k] extends string ? k : never }[keyof T]

const {options, optionLabel = 'label' as keyofString, optionValue = 'value' as keyof T} = defineProps<{
  options: Partial<T>[], // костыль 1
// когда на вход объединение из нескольких несовместимых типов (разный набор обязательных полей) ошибка по типу такой
// Type 'CategoryEntity[] | GroupEntity[] | SpecializationEntity[]' is not assignable to type 'CategoryEntity[]'.
//  Type 'GroupEntity[]' is not assignable to type 'CategoryEntity[]'.
//    Type 'GroupEntity' is not assignable to type 'CategoryEntity'.
//      Property 'service_groups' is missing in type 'GroupEntity' but required in type '{ id: string; name: string; order: number; // service_groups: GroupEntity[]; }'.ts-plugin(2322)
  optionLabel?: keyofString,
  optionValue?: keyof T
}>()
///
const filteredOptions = computed(() => {
  const tmp = filter.value
  if (tmp === '') return options
  return options.filter((el) => (el[optionLabel] as string).toLowerCase().includes(tmp)) // костыль 2
// без as string идет ошибка Property 'toLowerCase' does not exist on type 'Partial<T>[keyofString]'.ts-plugin(2339)
// хотя в optionLabel только ключи, у которых в объекте значения типа string (и это работает)
})


буду благодарен, если поможете избавиться от костылей
  • Вопрос задан
  • 47 просмотров
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы