英文:
Get the right type in a function from multiple possible type in typescript
问题
我有点困惑,不知道如何解决我的问题,尽管我已经在类似主题上看到了很多答案。
我有以下类型 - 我稍后会添加更多(大致每个表单一个):
export interface FormError {
formError: string
}
export interface InputState<T> {
value: T
onError: boolean
validation: FormDataValidation[] | undefined
errorMessage?: string
}
export interface WorkoutForm extends FormError {
trainingType: InputState<trainingType>
name: InputState<string>
date: InputState<string>
}
export interface LoginForm extends FormError {
email: InputState<string>
password: InputState<string>
}
我有以下函数,我想能够使用“通用”类型,以便我可以在WorkoutForm
或LoginForm
或以后创建的其他表单中使用它。
我已经尝试使用T
来解决我的问题,但是我的linter每次都会给我很多错误。
public validate<T>(formData: T, index: Exclude<keyof T, 'formError'>): T {
const validation = formData[index].validation; // << Property 'validation' does not exist on type 'T[Exclude ]'
// ....... code
return formData;
}
我想能够像这样使用它,例如:
function handleFormData(index: Exclude<keyof LoginForm, 'formError'>, value: string): void {
// ... some code
const currentFormData = formData; // currentFormData type is LoginForm
currentFormData[index].value = value;
const validatedData = FormValidation.getInstance().validate<LoginForm>(currentFormData, index);
// ... some code
}
有没有解决这个问题的提示或想法?
英文:
I'm having a bit of trouble figuring out how to solve my problem, despite the many answers I've already see on similar subjects.
I have the following types -- I'll add more later (one for each form roughly):
export interface FormError {
formError: string
}
export interface InputState<T> {
value: T
onError: boolean
validation: FormDataValidation[] | undefined
errorMessage?: string
}
export interface WorkoutForm extends FormError {
trainingType: InputState<trainingType>
name: InputState<string>
date: InputState<string>
}
export interface LoginForm extends FormError {
email: InputState<string>
password: InputState<string>
}
I have the following function where I'd like to be able to use a "generic" type so that I can use it with WorkoutForm
or with LoginForm
or with others that I'll create later.
I've tried to solve my problem with T
but my linter gives me lots of errors every time.
public validate<T>(formData: T, index: Exclude<keyof T, 'formError'>): T {
const validation = formData[index].validation; // << Property 'validation' does not exist on type 'T[Exclude ]'
// ....... code
return formData;
}
I'd like to be able to use it like this, for example:
function handleFormData(index: Exclude<keyof LoginForm, 'formError'>, value: string): void {
// ... some code
const currentFormData = formData; // currentFormData type is LoginForm
currentFormData[index].value = value;
const validatedData = FormValidation.getInstance().validate<LoginForm>(currentFormData, index);
// ... some code
}
Any tips or idea to solve this problem?
答案1
得分: 1
You should make validate()
generic in both T
, the type of formData
, as well as K
, the type of index
. Additionally, you should constrain T
and K
so that K
is a keylike type, and T
is known to be an object with a property whose key type is K
and whose value type is some InputState<any>
(you can use unknown
instead of any
as long as InputState<T>
is covariant in T
, see here for more information). That can be written as Record<K, InputState<any>>
using the Record<K, V>
utility type. Like so:
function validate<T extends Record<K, InputState<any>>, K extends PropertyKey>(
formData: T, index: K): T {
const validation = formData[index].validation;
return formData;
}
That compiles with no error, and now the rest of your code behaves as desired.
英文:
You should make validate()
generic in both T
, the type of formData
, as well as K
, the type of index
. Additionally, you should constrain T
and K
so that K
is a keylike type, and T
is known to be an object with a property whose key type is K
and whose value type is some InputState<any>
(you can use unknown
instead of any
as long as InputState<T>
is covariant in T
, see https://stackoverflow.com/q/66410115/2887218 for more information). That can be written as Record<K, InputState<any>>
using the Record<K, V>
utility type. Like so:
function validate<
T extends Record<K, InputState<any>>,
K extends PropertyKey>(
formData: T, index: K): T {
const validation = formData[index].validation;
return formData;
}
That compiles with no error, and now the rest of your code behaves as desired.
<!-- edit -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论