There is a function that takes a certain set of arguments. In particular, a callback function that takes as an argument an object or an array of objects that depends on another isArray parameter.
I'm trying to make an addiction.
type Option = {
name: string
value: string
> }
type FunctionProps<IsArray extends boolean | undefined> = {
isArray?: IsArray
callback: IsArray extends false
> ? (options: Option) => void
> : (options: option[]) => void
> }
const func = <T extends boolean | undefined = false>({isArray, callback}: FunctionProps<T>) => {
const options: Option[] = /* */
const currentOption: Option = /* */
if (isArray) {
callback(options) // Argument of type 'Option[]' is not assignable to parameter of type 'Option & Option[]'.
else {
callback(currentOption) // Argument of type 'Option' is not assignable to parameter of type 'Option & Option[]'.
> }
> }
When calling func, everything works as it should, but when calling callback inside func, typescript wants to get the intersection of the types Option & Option[]
as an argument. I can explicitly specify the type when calling callback(value as Option & Option[])
, but this makes it difficult to understand, and it is not clear what eventually happens inside.
Is it possible to define the type more clearly inside? P.S. If I declare the function type like this, nothing will change
type FunctionProps = {
isArray: false
callback: (options: Option) => void
} | {
isArray: true
callback: (options: Option[]) => void
}
CodePudding user response:
Narrowing callback
based on isArray
would require a discriminated union FunctionProps
is not a discriminated union so TS will not be able to follow the relationship between the property types.
IN this case a better option is to make FunctionProps
a discriminated union and not use a type parameter:
type FunctionProps = {
isArray?: false
callback: (options: Option) => void
} | {
isArray: true
callback: (options: Option[]) => void
}
const func =({ isArray, callback }: FunctionProps) => {
const options: Option[] = null!
const currentOption: Option = null!;
if (isArray) {
callback(options)
} else {
callback(currentOption)
}
}