Given a class, containing both properties and methods, I'd like to derive a type that just contains its properties.
For example, if I define a class as follow:
class MyObject {
constructor(public prop1: string, public prop2: number) {}
instanceMethod() { ... }
}
I'd like to have a type, say MyObjectConstructor
that would be like this:
type MyObjectConstructor = {
prop1: string;
prop2: number;
}
I know I can use the built-in type Pick
and manually select the keys I want by name, but I don't want to have to repeat the keys all over, and have to change them every time I add new properties to my class.
Is there a way to define a generic type ConstructorType<T>
that only returns the properties of a class in typescript ?
TypeScript treats a class as both value and type. This implicit type declared by TypeScript describes the shape of the instance a class produces. Therefore when a class is used as a type, such as using let value :Class annotation, TypeScript checks if the value has all the public properties of the Class .
In the highlighted code, you added a parameter called name of type string to your class constructor. Then, when creating a new instance of the Person class, you are also setting the value of that parameter, in this case to the string "Jane" . Finally, you changed the console. log to print the argument to the screen.
The TypeScript Omit utility type It will remove the fields you defined. We want to remove the id field from our user object when we want to create a user. type UserPost = Omit<User, 'id'>; const updateUser: UserPost = { firstname: 'Chris', lastname: 'Bongers', age: 32, };
In TypeScript, the constructor method is always defined with the name "constructor". In the above example, the Employee class includes a constructor with the parameters empcode and name . In the constructor, members of the class can be accessed using this keyword e.g. this. empCode or this.name .
I've found a way to exclude all properties that match a given type, thanks to this article: https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c
I made a few adaptations, but here is the details:
// 1 Transform the type to flag all the undesired keys as 'never'
type FlagExcludedType<Base, Type> = { [Key in keyof Base]: Base[Key] extends Type ? never : Key };
// 2 Get the keys that are not flagged as 'never'
type AllowedNames<Base, Type> = FlagExcludedType<Base, Type>[keyof Base];
// 3 Use this with a simple Pick to get the right interface, excluding the undesired type
type OmitType<Base, Type> = Pick<Base, AllowedNames<Base, Type>>;
// 4 Exclude the Function type to only get properties
type ConstructorType<T> = OmitType<T, Function>;
Try It
There might be a simpler way, I've tried playing with ConstructorParameters
and defining a constructor signature but without results.
Update
Found an equivalent while browsing the typescript documentation here: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types
type NonFunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];
type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;
It's a bit less verbose since the omitted type is not generic, but it's the same idea.
Given a class, containing both properties and methods, I'd like to derive a type that just contains its properties.
From your example, it seems like you want the result to contain only fields (as opposed to only properties). Here is a type that picks out the fields from an object or class instance.
type DataPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];
type DataPropertiesOnly<T> = {
[P in DataPropertyNames<T>]: T[P] extends object ? DTO<T[P]> : T[P]
};
export type DTO<T> = DataPropertiesOnly<T>;
I have used the acronym DTO
to mean Data Transfer Object. Thank you to l00ser2410656 for this playground demo.
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