I'm trying to set a Generic type that will accept 2 parameters and return a function.
First parameter - The type of the single parameter of the returned function
Second Parameter - need to get true if dev wants the returned function parameter to be required.
Somehow it's just not working The Val is inferred to string but it still thinks it's not a string
Any help will be appreciated
// Mandatory = true for required parameters
export type ValidationFunction<T = unknown, IsMandatory = unknown> =
<Val = IsMandatory extends true ? T : T | undefined>(val: Val) => true | string;
const test: ValidationFunction<string, true> = (val) => { // error!
// ~~~~
// Type 'Val' is not assignable to type 'string | true'.
return val;
};
test('poop')
// Maybe the core of the issue but weirdly it accepts
// any type of parameter I'll pass to it
test(555)
test(true)
test(null)
test({})
CodePudding user response:
Invalid answer:
Looks to me like you're saying that your ValidationFunction
for some reason wants to always return string | true
- why?
I'd just do it like that
export type ValidationFunction<T = unknown, IsMandatory = unknown> =
<Val = IsMandatory extends true ? T : T | undefined>(val: Val) => T;
test('poop') // no warnings
test(555) // warning
test(true) // warning
test(null) // warning
test({}) // warning
test([]) // warning
Valid answer:
// Mandatory = true for required parameters
export type ValidationFunction<T = unknown, IsMandatory = unknown> =
(val: IsMandatory extends true ? T : T | undefined) => true | string;
const test: ValidationFunction<string, true> = (val) => {
return val;
};
test('poop')
// Maybe the core of the issue but weirdly it accepts any type of parameter I'll pass to it
test(555)
test(true)
test(null)
test({})
Answer by @jcalz in the comment of the OP's question.
CodePudding user response:
The problem is that you are making ValidationFunction<T, M>
itself a generic function with one type parameter Val
which has a default of IsMandatory extends true ? T : T | undefined
. But it doesn't look like you intend for it to be generic at all, and even if you did, the type parameter Val
merely defaults to something; it isn't constrained at all. So test
accepts and returns a completely unconstrained Val
, which may or may not have anything to do with string
.
If you change the default to a constraint, things start working how you want:
export type ValidationFunction<T = unknown, IsMandatory = unknown> =
<Val extends IsMandatory extends true ? T : T | undefined>(val: Val) => true | string;
// ^^^^^^^ <-- constraint, not default
const test: ValidationFunction<string, true> = (val) => {
return val;
}; // okay
test('