Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to constraint a generic type to plain objects only in typescript?

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())
like image 638
sidoshi Avatar asked Apr 05 '19 09:04

sidoshi


People also ask

How do you pass a generic type in TypeScript?

Assigning Generic ParametersBy passing in the type with the <number> code, you are explicitly letting TypeScript know that you want the generic type parameter T of the identity function to be of type number . This will enforce the number type as the argument and the return value.

What TypeScript keyword is used to apply a constraint to a generic type parameter?

Use extends keyword to constrain the type parameter to a specific type.

What is generic type constraint?

A type constraint on a generic type parameter indicates a requirement that a type must fulfill in order to be accepted as a type argument for that type parameter. (For example, it might have to be a given class type or a subtype of that class type, or it might have to implement a given interface.)

What encloses a generic in TypeScript?

In TypeScript, the syntax for generics is rather simple. We use angle brackets to enclose the generic type-parameter.


1 Answers

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
like image 101
Titian Cernicova-Dragomir Avatar answered Sep 28 '22 10:09

Titian Cernicova-Dragomir