In order to support both array and object destructuring, I have the following Result
type definition:
type Errors = Record<string, string | null>
type Result = [Errors, boolean] & { errors: Errors, success: boolean }
I have tried to construct such result in one statement, but could not find syntax that could do such a thing... Also, this other approach fails with error:
const result: Result = [errors, success]
result.errors = errors
result.success = success
return result
Type '[Errors, boolean]' is not assignable to type 'Result'.
Type '[Errors, boolean]' is not assignable to type '{ errors: Errors; success: boolean; }'
However, declaring result as any
and applying type on the return works:
const result: any = [errors, success]
result.errors = errors
result.success = success
return result as Result
Is there better, type safe way to construct such object?
CodePudding user response:
Problems like this where you want an object to be both A
and B
at the same time but can't do an assignment in one line can often be solved with Object.assign()
. This function allows combining two JavaScript objects at runtime and is also conveniently typed to intersect both object types.
The only problem in this case is the way that TypeScript types array literals. We need an assertion to tell TypeScript to type the passed array as a tuple.
const result: Result = Object.assign(
{ errors, success },
[errors, success] as [Errors, boolean]
)
This reduces the type-safety as the type assertion allows us to forget an element in the tuple or to add some other element.
You could type Result
to be an readonly
array.
type Result = readonly [Errors, boolean] & { errors: Errors, success: boolean }
Then we could use as const
.
const result: Result = Object.assign(
{ errors, success },
[errors, success] as const
)
Which would give us 100% type-safety.