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'
как я могу решить эту проблему?
очевидно, проблема связана с общим параметром типа, поскольку он неправильно ограничен
Соответствует ли такой подход вашим потребностям? Если да, то я напишу ответ с объяснением; если нет, то что мне не хватает?
@jcalz клянусь. это работа. Спасибо.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Чтобы исправить проблему с типом 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).
Я пытался, но не работал.
Это дает ошибку в поле class при вызове функции и позволяет передать любую строку
@wonderflame да, хорошо
Это создано ИИ? Или он просто не работает должным образом? В любом случае, этот ответ нуждается в некоторой помощи.
Один из подходов состоит в том, чтобы сделать 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". Таким образом, это решение работает как для принятия желательных входных данных, так и для отклонения нежелательных.
включить
FilterValidationиTestValidation