Reputation:
I am trying to write typings for a class (originally Javascript) that has a property named camelcaseKeys
. If it is set to true, then all of the methods that make an API call return an object with the properties converted to camelCase, and if it is set to false they are returned in snake_case.
const api = new APIClass("username", "password", {camelcaseKeys: true});
(async () => {
await api.login()
/*Returns an object with camelCase or snake_case keys,
depending on the value of camelcaseKeys.*/
let result = api.getLoginInfo()
})()
I defined two interfaces for each response with all the properties set to either camelCase or snake_case, however I don't know how to make typescript pick one conditionally.
//Doesn't work, type is camelType | snake_type
public getLoginInfo<T extends this>(): T["camelcaseKeys"] extends true
? camelType : snake_type
//Doesn't work, type is camelType | snake_type
type GetCase<T extends APIClass, C, S> = T["camelcaseKeys"] extends true ? C : S
public getLoginInfo(): GetCase<this, camelType, snake_type>
I don't know what else to try. Thank you for any help!
Upvotes: 3
Views: 1562
Reputation: 328272
Without your APIClass
definition I'll have to make stuff up as I go along. The basic issue here is that if APIClass
needs to keep track of whether it is a camel-case type or a snake-case type, this distinction will need to be part of the class type itself. I'd do that by making APIClass
generic in the relevant boolean type:
class APIClass<B extends boolean> {
constructor(
public username: string,
public password: string,
public options: { camelcaseKeys: B }
) {}
public async login() {}
public getLoginInfo(): B extends true
? camelType
: snake_type {
return null!; // implement me later
}
}
So now the return type of getLoginInfo()
will depend on B
in the way you want:
const api = new APIClass("username", "password", { camelcaseKeys: true });
(async () => {
await api.login();
let result = api.getLoginInfo(); // cameltype
})();
Please note that values of conditional types like B extends true ? camelType : snake_type
are easy to use when you know what B
is, and harder to use if B
is still an unresolved generic type parameter. So the implementation of getLoginInfo()
might require you use some type assertions or the like to convince the compiler that the thing you're returning matches the type. But you're not asking about implementation, so I'll leave it there.
Okay, hope that helps; good luck!
Upvotes: 4