Reflect upon the subsequent categorization and forms:
type keyCollection = {
[key: string]: {
request: any,
response: any
}
}
class customTestClass<TData extends keyCollection = any> {
testFunction<
TInput extends keyof TData,
TObject = TData extends keyCollection ? TData[TInput]['request'] : any>(input: TInput, data: TObject) {}
}
My intention is that if this class is created without specifying generic parameters, the testFunction
should permit any string
as its first parameter, and any value as its second parameter. However, when a generic type is provided to the class, it should restrict the values of the testFunction
.
Consider the following scenarios:
let x: customTestClass = new customTestClass();
x.testFunction('sample', {}); // functions as intended; no generics specified for the class, hence accepts string as first parameter and anything as second
type sampleGenericKeyCollection = {
a: {
'request': string,
'response': any
},
b: {
'request': string,
'response': any
}
}
let y: customTestClass<sampleGenericKeyCollection> = new customTestClass();
y.testFunction("c", 25); // shows correct error; "c" is not a property of the generic
y.testFunction("a", 25); // why no error here? 25 is of type number, not string - also, why no type enforcement in this case?
Comments indicate that instantiation without generics works in the initial test scenario - function accepts any string as its first parameter and any value as its second.
In the second situation, with generics provided during instantiation, testFunction
fails to accept "c" as its first parameter because it is not a property of the given generic.
However, in the third test-case, even though the function identifies the key from the input correctly, it allows any type as the second parameter, which I cannot comprehend. The third test-case should allow only a string
type as its second parameter.
Why does the functionality differ from my expectations?
Fiddle here