Reputation: 3705
Let's see I want to build a function:
type A = {
foo: boolean
};
type B = {
bar: boolean
}
type PossibleObjects = A | B
type Object <T> = {
[key in keyof T]?: boolean
}
const fn = <
T //:PossibleObjects
>(object: Object<T>) => object;
Even though this function doesn't make anything useful, it's good to explain what I want. I want to control what T
can be, in this case A
or B
.
Is that possible?
Upvotes: 1
Views: 47
Reputation: 51152
The keyword extends
sets an upper bound on a type argument. This works both on type declarations and on function declarations.
type SomeObject<T extends PossibleObjects> = {
[key in keyof T]?: boolean
}
const fn = <T extends PossibleObjects>(obj: SomeObject<T>) => obj;
Note that T
here isn't constrained to be either A
or B
; T
could also be PossibleObjects
itself. I don't think there is a way to prohibit that, but you should be aware of it.
Upvotes: 1
Reputation: 5428
You can achieve that by narrowing the generic type T
to extend your possible Objects.
type A = { foo: boolean };
type B = { bar: boolean };
type PossibleObjects = A | B
type SomeObject <T> = { // Renamed to "SomeObject" since "Object" is already a default type
[key in keyof T]?: boolean
}
const fn = <T extends PossibleObjects> // This makes T a subtype of PossibleObjects
(object: SomeObject<T>) => object;
fn({ foo: true }); // Works
fn({ bar: true }); // Works
fn({ baz: true }); // Error: Argument of type '{ baz: boolean; }' is not assignable to parameter of type 'SomeObject<A> | SomeObject<B>'.
If your SomeObject
type can only ever (and not just in your fn
function) specify keys that are in your PossibleObjects
type, you might want to do this on your SomeObject
type as well.
type A = {
foo: boolean
};
type B = {
bar: boolean
}
type PossibleObjects = A | B
type SomeObject <T extends PossibleObjects> = { // Adds the type constraint here
[key in keyof T]?: boolean
}
// Now the following works
const fn = <T extends PossibleObjects>(object: SomeObject<T>) => object;
// But this one will NOT be valid anymore
const fn2 = <T>(object: SomeObject<T>) => object;
// Error: ^
// Type 'T' does not satisfy the constraint 'PossibleObjects'.
Upvotes: 1
Reputation: 171
Use the pipe (|) operator to provide different types:
function fn(arg: A | B): any {
// code
}
Upvotes: 0