You can use the object de-structuring syntax:
createUser(parent: any, { data }: { data: UserCreateInput }, context: any) {
return context.prisma.createUser(data)
}
Unfortunately it is required you write data twice. There is a proposal to fix this but there are issues around this.
You can use the object de-structuring syntax:
createUser(parent: any, { data }: { data: UserCreateInput }, context: any) {
return context.prisma.createUser(data)
}
Unfortunately it is required you write data twice. There is a proposal to fix this but there are issues around this.
A widely used and arguably less ugly alternative to inline object types is to define the destructured object as a named args or props type. For example:
interface CreateUserArgs {
data: UserCreateInput
}
createUser(parent: any, { data }: CreateUserArgs, context: any) {
return context.prisma.createUser(data)
}
Sadly it still requires duplicating the property names (and means you need to give it a name), but it has two potential benefits:
- It doesn't fill the arguments list with brackets, so it's easier to see what the top-level arguments are and how many there are
- The type can be exported and used in other files (e.g. by consumers of this function if building the object of args is not just inline when the function is called
Simplify object destructuring in argument
Why is function parameter destructuring so bad in TypeScript?
typescript - Destructuring a function parameter object and ...rest - Stack Overflow
Narrowing the type of destructured object arguments
Function parameter destructuring in JavaScript is glorious and I love it. It's clean, simple, readable, and almost intuitive. However, in TypeScript, parameter destructuring is ugly and tedious.
A sample taken from an online tutorial:
function getObjValues({ key1, key2 }: { key1: string; key2: number }) {}Could this be any more redundant? Is there not any way to do this without repeating object keys more than once? Even with an interface, that still requires a separate definition and creates just as much (if not more) redundancy.
One of JS's biggest pros, in my opinion, is the cleanliness of inline function parameter destructuring. I'm disappointed that this feature has not made its way over to TypeScript.
You can use destructuring assignment directly in the function arguments:
interface IMyType {
a: number;
b: number;
c: number;
d: number;
[k: string]: number; // use this if you don't know the name of the properties in 'rest'
}
const obj: IMyType = { a: 1, b: 2, c: 3, d: 4 }
// Normal destructuring
const { a, b, ...rest } = obj;
console.log(rest); // {c: 3, d: 4}
// Directly in function arguments
const fn = ({ a, b, ...rest }: IMyType) => { console.log(rest); }
console.log(fn(obj)); // {c: 3, d: 4}
UPDATE:
Given the PR at microsoft/TypeScript#28312, you could now use generics, like this:
const myfun1 = <T extends IMyProps>(p: T) => {
const { a, b = 'hello', ...rest } = p;
a; // string
b; // number | 'hello'
rest; // const rest: Pick<T, Exclude<keyof T, "a" | "b">>
}
in which the rest variable is inferred to be of type Omit<T, "a" | "b">, which is probably what you want.
Pre TS4 answer
I think object destructing with the rest operator in TypeScript corresponds to the index signature on the type of the destructured object if you have pulled off all the explicitly named properties already. That means you would have the same restriction where the types of the rest properties would have to be at least as wide as the union of all the explicitly labeled properties. In your case, you could extend IMyProps with an index signature like this:
interface IMyPropsWithIndex {
a: string
b?: number
[k: string]: string | number | undefined
}
since the type of a is string and the type of b is number | undefined. You could add more stuff to the union but you couldn't make it something narrower like string. If that's okay with you, then the way to do destructuring would be something like this:
const myfun1 = (p: IMyPropsWithIndex) => {
const { a, b = 'hello' , ...rest } = p;
a; // string
b; // number | 'hello'
rest; // {[k: string]: string | number | undefined}
}
If you inspect the types of the variables, you get something like the above.
Playground link to code