Как исправить проблему с динамическим типом typescript

function Middleware<T extends Function>(middleware: Array<{ funcs: Array<keyof T['prototype']>, class: T }>) {

}

class TestValidation {
  Test() { }
}

class FilterValidation {
  Filter() { }
}

Я определяю Middleware fonkisyon и хочу использовать функции предоставления класса в виде строки. Но не работает.

пример использования

Middleware([
    { funcs: ['Test'], class: TestValidation },
    { funcs: ['Filter'], class: FilterValidation}
  ]) 

этот код дает ошибку Type '"Filter"' is not assignable to type 'keyof TestValidation'

как я могу решить эту проблему?

включить FilterValidation и TestValidation

wonderflame 08.07.2023 15:16

очевидно, проблема связана с общим параметром типа, поскольку он неправильно ограничен

wonderflame 08.07.2023 15:17

Соответствует ли такой подход вашим потребностям? Если да, то я напишу ответ с объяснением; если нет, то что мне не хватает?

jcalz 08.07.2023 18:23

@jcalz клянусь. это работа. Спасибо.

Erdem Ün 08.07.2023 20:39
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4
4
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Чтобы исправить проблему с типом TypeScript в вашем коде, вы можете внести небольшую модификацию. Вместо того, чтобы определять funcs как массив ключей T['prototype'], вы можете определить его как массив строк, представляющих имена функций. Вот обновленная версия вашего кода:

function Middleware<T extends { prototype: Record<string, any> }>(middleware: Array<{ funcs: Array<keyof T['prototype']> | string[], class: T }>) {
  // Your implementation here
}

// Example usage
class TestValidation {
  Test() {
    // Implementation of Test function
  }
}

class FilterValidation {
  Filter() {
    // Implementation of Filter function
  }
}

Middleware([
  { funcs: ['Test'], class: TestValidation },
  { funcs: ['Filter'], class: FilterValidation }
]);

Определив функции как Array<keyof T['prototype']> | string[], он допускает как ключи прототипа, так и строковые представления имен функций. Это изменение устранит ошибку, с которой вы столкнулись.

Примечание. В примере использования убедитесь, что вы определили классы TestValidation и FilterValidation с соответствующими функциями (Test и Filter).

Я пытался, но не работал.

Erdem Ün 08.07.2023 15:20

Это дает ошибку в поле class при вызове функции и позволяет передать любую строку

wonderflame 08.07.2023 15:20

@wonderflame да, хорошо

Erdem Ün 08.07.2023 15:20

Это создано ИИ? Или он просто не работает должным образом? В любом случае, этот ответ нуждается в некоторой помощи.

jcalz 09.07.2023 17:38
Ответ принят как подходящий

Один из подходов состоит в том, чтобы сделать Middlewareуниверсальным в параметре типа T, соответствующем типу кортежа типов экземпляров, созданных свойством class массива middleware. Итак, если вы вызываете Middleware([{funcs: [], class: Class1}, {funcs: [], class: Class2}]), где Class1 и Class2 — конструкторы классов типов с именами Class1 и Class2 соответственно, то T будет типом [Class1, Class2].

И мы бы сделали параметр middleware типа , отображаемого поверх T, так что каждый элемент middleware принимает тип, связанный с соответствующим элементом T. Для каждого числового индекса I из ключей T свойство class должно быть сигнатурой конструкции для T[I] (элемент T по ключу I), а свойство funcs должно быть массивом ключей T[I], свойства которых являются функциями .

Мы можем написать это так:

function Middleware<T extends readonly object[]>(
  middleware: [...{ [I in keyof T]: {
    funcs: ReadonlyArray<KeysMatching<T[I], Function>>
    class: new () => T[I]
  } }]
) {}

где KeysMatching<T, V> — тип утилиты для получения ключей свойств T, значения свойств которых можно присвоить V. Одно из возможных определений

type KeysMatching<T, V> = keyof
  { [K in keyof T as T[K] extends V ? K : never]: any }

См. Как в TypeScript получить ключи типа объекта, значения которого имеют заданный тип? для получения дополнительной информации о том, как работает KeysMatching.

О, и тип параметра middleware заключен в вариативный тип кортежа, например [...+], чтобы дать компилятору подсказку, что мы хотим, чтобы T выводился как кортеж, а не неупорядоченный массив.


Хорошо, давайте проверим это:

class TestValidation { Test() { } }
class FilterValidation { Filter() { } }

Middleware([
  { funcs: ['Test'], class: TestValidation },
  { funcs: ['Filter'], class: FilterValidation }
]); // okay

Выглядит неплохо. Давайте проверим это на примере, который не работает:

class Foo {
  a = 1;
  b = 2;
  c() { }
}
Middleware([{
  class: Foo, funcs: ["a", "b", "c"]; // error!
  // ---------------> ~~~  ~~~
}])

Это не удается, потому что "a" и "b" являются ключами Foo, значения которых не являются функциями. Принимается только "c". Таким образом, это решение работает как для принятия желательных входных данных, так и для отклонения нежелательных.

Площадка ссылка на код

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