Closed
Description
TypeScript Version: 2.5.3
Would it be possible to have something like the keyof
operator for arrays? The operator would be able to access the values in the array.
Code
With object we can do the following:
const obj = {one: 1, two: 2}
type Prop = {
[k in keyof typeof obj]?: string;
}
function test(p: Prop) {
return p;
}
test({three: '3'}) // throws an error
Could we do something like the following with arrays?
const arr = ['one', 'two'];
type Prop = {
[k in valuesof arr]?: string;
}
function test(p: Prop) {
return p;
}
test({three: '3'}) // throws an error
Activity
DanielRosenwasser commentedon Jan 2, 2018
You can get
valuesof arr
with the indexed access type(typeof arr)[number]
, but you'll getstring
instead of"one" | "two"
without an explicit type annotation. #10195 would help there though.bezreyhan commentedon Jan 2, 2018
Thanks @DanielRosenwasser, #10195 would be helpful but ideally we would be able to do without indexed access types. What I was looking for was a way to express: "All keys in an object must be a value in an array".
DanielRosenwasser commentedon Jan 2, 2018
You could always define a type alias for that, but you won't be able to get around using
typeof
in conjunction with it.bezreyhan commentedon Jan 2, 2018
That's interesting, I didn't think of that. I'll close out the ticket. Thanks!
kpdonn commentedon Mar 3, 2018
@bezreyhan I came across this issue while searching around for something else. I don't know if this will be useful to you two months later but I think this will do essentially what you want as long as you don't need to save the array in a variable beforehand:
If you do need the array in a variable, it looks like this will work:
Here is a link of those examples in the playground: Link
tomzaku commentedon Jun 15, 2018
@kpdonn Thanks. But I have problem with using array variable instead of direct array in parameter
nickserv commentedon Jun 16, 2018
Using resolveJsonModule, would it be possible to get the type of a JSON array without explicitly declaring the type of the JSON module and losing typechecking on its data? I tried the ValuesOf approach but it seems like I would have to declare the type of my function argument explicitly.
tpucci commentedon May 1, 2019
@kpdonn I find your solution very interesting.
Any idea how to have the same result with an array of object instead of an array of string ?
The following code passes typescript diagnostic. However, the last line should throw an error.
tpucci commentedon May 2, 2019
If anyone is interested, I found the solution of my problem:
NickDubelman commentedon May 15, 2019
Is there anything wrong with doing the following:
When I do that,
type Thing
has the correct type. Obviously you wouldn't want to do this by default, but I find myself in the situation where I have something generating array types, but sometimes I want functions to take a single value of that array and obviously I don't want to have to manually duplicate the type definition.The above syntax is kind of weird, but it seems to do the job?
benneq commentedon Jun 17, 2019
Typescript 3.4 made things better:
👍
Serrulien commentedon Jul 10, 2019
@benneq Thanks for that hint. I'm now able to type function's parameter without having to create an
enum
bopfer commentedon Jul 12, 2019
Is there a way to do what @Serrulien posted, but also with types defined for each object in the array?
Something like:
Then enforce that type of each object of the
const
array. With an array of many elements, it would help to avoid type errors in any individual object.14 remaining items
daniel-nagy commentedon Nov 29, 2019
Is there a way to get a literal type from an iterative operation?
I want the literal type of the result.
I'd also like to create a generic type to represent this function
AmirTugi commentedon Jan 1, 2020
This is the release note with the relevant info about the solution (which @benneq mentioned)
daniel-nagy commentedon Jan 1, 2020
Using
const
does not solve the problem for me.I'm trying to get a literal type from an operation on a literal type. I think the issue is
K[number]
will return a union type which has no understanding of order.fabb commentedon Jan 1, 2020
@daniel-nagy
T[K[number]][]
results in an array, but you want a tuple. You can keep the tuple type when you take advantage of mapped type support used like this:{ [P in keyof T]: X }
whereT
is the tuple. As far as I have understood, thekeyof T
is the tuple array index (since arrays in JS are just objects with indexes as keys), and this syntax builds a new tuple with the same indexes.All together this nearly works as expected:
While the result type is now correctly
[1, "three"]
, TypeScript shows an error:Type 'K[P]' cannot be used to index type 'T'.
. I think this is a bug in TypeScript, maybe related to #21760 or #27413.Here's a small workaround that fixes this error 🎉:
7kms commentedon Jul 22, 2020
in the latest ts "version": "3.9.6"
Sharcoux commentedon Jul 30, 2020
For a value, I found that I can use:
derekslarson commentedon Oct 25, 2020
For what I am doing, something like this is sufficient:
I specifically need this functionality for generating specific
APIGatewayProxyEventV2
types for lambda integrations:Spodera commentedon Oct 31, 2020
For simple array, I do this (add "readonly type")
KrzysztofMadejski commentedon Dec 31, 2020
I use two approaches:
isumix commentedon Jun 26, 2021
I just managed to make my function return a type checkable object:
Here the type checker will complain:
add types to useCookie hook
paulwongx commentedon Dec 26, 2021
As mentioned above by @7kms this works to change an array into a type