Reputation: 16895
Let's assume there's a function that returns an object whose property types can either be inferred or are explicitly provided:
const myFn = (arg: number) => {
return {
a: 1 + arg,
b: 'b' + arg,
c: (() => { return arg + 'c'})()
}
}
We can then destructure the returned object and assign to new variables:
const { a, b, c } = myFn(10);
console.log('used once', a, b, c);
All nice and dandy. Now let's assume we'll need to reassign to those same variables later on, more specifically in a switch statement. In order to prevent Cannot redeclare block-scoped variable 'xyz'. ts(2451)
we'll take advantage of assignment without declaration and proceed like so:
let my_a, my_b, my_c;
switch (true) {
case Math.random() < 0.5:
({a: my_a, b: my_b, c: my_c} = myFn(Math.random()));
console.log('called at one point', my_a, my_b, my_c);
default:
({a: my_a, b: my_b, c: my_c} = myFn(Math.random()));
console.log('called at another point', my_a, my_b, my_c);
}
The question is then, how can I declare/extract the types of my_a
, my_b
etc when I know what they're going to be and don't want to manually type them out? Here's a playground snippet.
ELABORATION
What I'm looking for is a way to declare the types when I initialize the vars using
let my_a, my_b, my_c;
based on what I know about the signature of myFn
to prevent
Variable 'my_a' implicitly has an 'any' type,
but a better type may be inferred from usage. ts(7043)
Upvotes: 0
Views: 805
Reputation: 186994
If you just want to explicitly type the my_*
variables ahead of time, then you can do that by drilling into the return type of your function.
let my_a: ReturnType<typeof myFn>['a'],
my_b: ReturnType<typeof myFn>['b'],
my_c: ReturnType<typeof myFn>['c'];
typeof myFn
gets the function type from the myFn
so the type system can work with it. ReturnType<...>
will get the type that function returns. And, lastly, ['a']
will get the a
property from that return type.
This isn't really required though. Your playground snippet infers everything correctly and raises no type errors. So I would think about whether this is really necessary.
Upvotes: 2
Reputation: 2732
You can declare an interface and place your switch logic inside anonymous arrow functions:
interface Alphabet {
a: number,
b: string,
c: string,
}
const myFn = (arg: number): Alphabet => {
return {
a: 1 + arg,
b: 'b' + arg,
c: (() => { return arg + 'c'})()
}
}
let my_a, my_b, my_c;
switch (true) {
case Math.random() < 0.5:
() => {
const {a: my_a, b: my_b, c: my_c}: Alphabet = myFn(Math.random());
console.log('called at one point', my_a, my_b, my_c);
}
default:
() => {
const {a: my_a, b: my_b, c: my_c}: Alphabet = myFn(Math.random());
console.log('called at one point', my_a, my_b, my_c);
}
}
Upvotes: 2