If I have a type which looks like an array:
type names = ['Mike', 'Jeff', 'Ben'];
I can easily define another type which has values of items in names
:
type UserName = names[number]
For a function:
function hello(name: UserName) {
console.log(`Hello, ${name}!`)
}
I can only pass one of Mike
, Jeff
, Ben
to function hello
. If I give other values, like John
, it can't compile.
What if I don't have a type names
, but a const array names
?
const names = ['Mike', 'Jeff', 'Ben'];
type UserName = ???;
function hello(name: UserName) {
console.log(`Hello, ${name}!`)
}
hello('Mike');
Is it possible to define such a type UserName
?
Summary. In TypeScript, an array is an ordered list of values. An array can store a mixed type of values. To declare an array of a specific type, you use the let arr: type[] syntax.
We identify the data type of the array elements, and the name of the variable, while adding rectangular brackets [] to denote its an array. Here are two valid ways to declare an array: int intArray[]; int[] intArray; The second option is oftentimes preferred, as it more clearly denotes of which type intArray is.
You can create an array with elements of different data types when declare the array as Object. Since System. Object is the base class of all other types, an item in an array of Objects can have a reference to any other type of object.
There are several ways to declare and int array: int[] i = new int[capacity]; int[] i = new int[] {value1, value2, value3, etc}; int[] i = {value1, value2, value3, etc};
In TypeScript 3.4, which should be released in March 2019 it will be possible to tell the compiler to infer the type of a tuple of string literals as a tuple of string literals, instead of as string[]
, by using the as const
syntax. It should look like this:
const names = ['Mike', 'Jeff', 'Ben'] as const; // TS3.4 syntax
type Names = typeof names; // type Names = readonly ['Mike', 'Jeff', 'Ben']
type UserName = Names[number]; // 'Mike' | 'Jeff' | 'Ben'
Until then (in TypeScript 3.0 through 3.3) you can get this effect by using a helper function which gives the compiler hints to infer a narrower type:
type Narrowable = string | number | boolean | undefined | null | void | {};
const tuple = <T extends Narrowable[]>(...t: T)=> t;
const names = tuple('Mike', 'Jeff', 'Ben');
type Names = typeof names; // type Names = ['Mike', 'Jeff', 'Ben']
type UserName = Names[number]; // 'Mike' | 'Jeff' | 'Ben'
(Note that in both cases you can skip the intermediate Names
type and just define type UserName = (typeof names)[number]
if you prefer)
Okay, hope that helps. Good luck!
Again, one should most of the time:
exactly in that order.
Rarely one should do the opposite thing.
If you really need it though, you can do it like this:
const names = ['Mike', 'Jeff', 'Ben'] as ['Mike', 'Jeff', 'Ben'];
type UserName = typeof names;
because you want a tuple type (['Mike', 'Jeff', 'Ben']
), but arrays are never inferred as tuples by default, but only as arrays (string[]
in this case). However I don't see much sense in doing above thing and again I am suggesting you to do the opposite, idiomatic thing:
type UserName = ['Mike', 'Jeff', 'Ben'];
// however the above type is absolutely static
// and I don't know if it can provide any benefit so maybe this is more correct:
type UserName = ('Mike' | 'Jeff' | 'Ben')[]
const names: UserName = ['Mike', 'Jeff', 'Ben'] // ok
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With