Reputation: 189
This is my interface:
interface MyInterface {
a: string
b: string
}
I have objectA
from this interface:
const objectA: MyInterface = {
a: val1,
b: val2
}
I then have a function that reads an API response and creates a mapping as follows:
const createMapping = (response) => {
const ret = {};
response.forEach(item => {
ret[objectA[item]] = true;
})
return ret;
}
Is there a way I can create an interface for the return value of createMapping
such that the interface's keys are the value of MyIterface
?
A return value could be {val1: true}
, {val2: true}
, or {val1: true, val2:true}
Upvotes: 3
Views: 1626
Reputation: 330086
I'm not really sure where objectA
comes from, but you can get what you want. First, wherever objectA
comes from, you should let TypeScript know that the values are particular string literal types. There are different ways to do this. The most straightforward (but not DRY) way is to use type assertions:
interface MyInterface {
a: string
b: string
}
const objectA = {
a: "val1" as "val1",
b: "val2" as "val2"
}
Note that objectA
is not being annotated as a MyInterface
, since you don't want TypeScript to forget that its properties are "val1"
and "val2"
. Its compatibility with MyInterface
will be verified later.
Now we can make a function which takes anything MyInterface
-like (with string properties) and produces a createMapping()
function which uses it:
const makeCreateMapping = <O extends MyInterface & {[k: string]: string}>(o: O) =>
(response: (keyof O)[]) => {
const ret = {} as Partial<Record<O[keyof O], true>>;
response.forEach(item => {
ret[o[item]] = true;
})
return ret;
}
The O
parameter is the type of your MyInterface
object. Let's call makeCreateMapping()
with objectA
:
const createMapping = makeCreateMapping(objectA);
That's where the fact that objectA
is a MyInterface
comes in. If it hadn't been, the compiler would have yelled at you. Now if you inspect the type of createMapping
, it is:
const createMapping: (response: ("a" | "b")[]) => Partial<Record<"val1" | "val2", true>>
That is, a function which takes an array of "a"
or "b"
, and returns a Partial<Record<"val1" | "val2", true>>
which is essentially {val1?: true, val2?: true}
whose valid values include {val1: true}
, {val2: true}
, and {val1: true, val2: true}
.
To demonstrate:
declare const response: (keyof typeof objectA)[]
const mapping = createMapping(response);
mapping.val1 // true | undefined
mapping.val2 // true | undefined
mapping.val3 // error, doesn't exist
Hope that helps. Good luck!
Upvotes: 2
Reputation: 2371
Yes, you can specify a return type or interface for the arrow function.
const createMapping = (response): MyInterface => {
const ret = {};
response.forEach(item => {
ret[objectA[item]] = true;
})
return ret;
}
In this case, when you execute the function createMapping
, the output (ret
) is expected to be of MyInterface
type.
Upvotes: 0
Reputation: 9258
You would only get the API response
values at runtime, at which point your TypeScript code has already been compiled away into JavaScript, so the answer is: no you would not be able to do this.
Upvotes: 1