I have a method like this:
public select(fieldName: keyof TType)
Where TType
could be an array type. In case of an array type, fieldName
will correctly offer me all the propertynames of type Array
.
In case I call this method with a type of User[]
I want to get to the properties of User
instead of the properties of Array
.
Is there any way of how this could be done?
Extra question: Is there any way to restrict TType to be of an array type?
In typescript, an array is a data type that can store multiple values of different data types sequentially. Similar to JavaScript, Typescript supports array declaration and there are multiple ways to do it. Declaring and Initializing Arrays: We can either use var or let for declaring an array.
TypeScript generic type They can be used to identify that specific called function as a type. Making the function itself unaware of which type it's working with. To identify a generic type, you must prefix the function with <Type> where Type is the generic variable. Note: We often use T for generic types.
An array in TypeScript can contain elements of different data types using a generic array type syntax, as shown below. let values: (string | number)[] = ['Apple', 2, 'Orange', 3, 4, 'Banana']; // or let values: Array<string | number> = ['Apple', 2, 'Orange', 3, 4, 'Banana'];
There is no difference at all. Type[] is the shorthand syntax for an array of Type . Array<Type> is the generic syntax. They are completely equivalent.
You can definitely make a conditional type function that unwraps an array type up to one level deep, and then use keyof
on the result of that. For example:
// unwrap up to one level
type Unarray<T> = T extends Array<infer U> ? U : T;
// your class maybe
declare class Thingy<T> {
constructor(t: T);
public select(fieldName: keyof Unarray<T>): void;
}
// your interface maybe
interface User {
name: string,
age: number
}
declare const u1: User;
declare const u2: User;
const x = new Thingy(u1);
x.select("name"); // okay
const y = new Thingy([u1, u2]);
y.select("age"); // okay
y.select("push"); // error
That should work as you want, for the typings, I think. Obviously you also need to have an implementation which works (and note that conditional types in implementations usually require some type assertions or overloads to make the compiler happy... but you seem to be asking about the typings, not the implementation).
As for your extra question, yes, you can restrict T
to just array types, as follows:
// your class maybe
declare class Thingy<T extends Array<any>> {
constructor(t: T);
public select(fieldName: keyof (T[number])): void;
}
// your interface maybe
interface User {
name: string,
age: number
}
declare const u1: User;
declare const u2: User;
const x = new Thingy(u1); // error
const y = new Thingy([u1, u2]);
y.select("age"); // okay
Note that I did away with the conditional types altogether here because it's more straightforward.
Hope that helps; good luck!
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