Reputation: 2160
Using typescript, is there a way to constraint a generic type to allow values of type object only? Not array and other types.
For eg:
function check<O extends object>(ob: O): O {
return ob
}
check({}) // should be fine
check([]) // should show error, but does not.
A possible real world use case:
function extend<A extends object, B extends object>(a: A, b: B): A & B {
return {
...a,
...b,
};
}
// This is fine, return type is { x: number } & { y: string }
extend({x: 5}, {y: "str"})
// This should not be allowed
// Return type is number[] & string[]
// Accessing a property yields impossible types like number & string
extend([1,2,3], ["s", "i", "d"])
// More examples for variants which I don't want to allow
extend({}, function() {})
extend({}, new Map())
Upvotes: 12
Views: 4603
Reputation: 41
In newer versions of Typescript, you can use object & Exclude<T, any[]>
to represent an object that cannot be an array.
Upvotes: 4
Reputation: 250366
You can use a conditional type to add to the parameter of the parameter if O
extends any[]
. What you add can ensure that the call will be an error. I usually add string literal types and think of them as a custom error message:
function check<O extends object>(ob: O & (O extends any[] ? "NO Arrays !" : {})): O
function check<O extends object>(ob: O): O {
return ob
}
check({}) // should be fine
check([]) // error
Upvotes: 6