When it comes to Typescript generics inference, the priority is given to arguments over assignment. This means that any param props are automatically converted into type unknown
, even if they are assigned to a variable whose type param is set to an object interface.
interface Person {
name: string;
age: number;
id: string;
}
interface Client {
person: Person;
}
class FormField { }
class FormFieldGroup<T> {
constructor(private props: { category: string, questions: FormRelation<Required<T>> }) {}
}
type Primitives = string | number | symbol | bigint | undefined | null;
type FormRelation<T> = {
[K in keyof T]: T[K] extends Primitives ? FormField : FormFieldGroup<T[K]>;
}
abstract class CRUDComponent<D> {
public abstract clientQuestions: FormRelation<D>
}
class ClientComponent extends CRUDComponent<Client> {
public clientQuestions: FormRelation<Client> = {
person: new FormFieldGroup({
category: "Client",
questions: {
name: new FormField(),
age: new FormField(),
id: new FormField(),
}
})
}
}
VScode: Cannot assign FormQuestionGroup<{name: unknown, age: unknown, id: unknown}> to FormQuestionGroup<Person>.
In Java, the diamond operator handles type inference based on the assignment type params. However, TypeScript does not have the diamond operator for clarity reasons. I am using TypeScript 3.7 and I am curious if there is a workaround for this issue other than explicitly specifying the type.
Furthermore, when setting props to an empty object, the compiler can correctly infer the Generic to the appropriate interface.