I initially thought my problem would be solved by conditional types, but upon further inspection it seems like discriminated unions would work better for my case.
These examples get really close to what I want, but I'm still confused on how to implement it in my real world example.
Say I have an interface, in this case it's the data I get back after logging in with Passport.js:
export interface UserInterface {
id: number
username: string
photos: {
values: string
}[]
provider: 'twitter' | 'github'
_json: TwitterProfileInterface | GithubProfileInterface
}
In the above, id
, username
and photos
are all interchangeable. However, the type of _json
depends on the value of provider
. So if provider
is twitter
, then _json
will be TwitterProfileInterface
.
Is there any way to make this automatic with Typescript?
EDIT: Example code:
I'm running a switch statement to check what type of User Profile I received:
const user = {
id: 1,
username: "User",
photos: [],
provider: "twitter",
_json: {
// a bunch of data specific to the "twitter" provider
}
};
switch(user.provider){
case 'twitter':
// this case will give types from both TwitterProfileInterface and GithubProfileInterface
break;
case 'github':
// this case will give types from both TwitterProfileInterface and GithubProfileInterface
break;
}
Even though I have a switch statement, the fact that the value I use for the switch is contained outside of either TwitterProfileInterface
and TwitterProfileInterface
then both cases will include both types, rendering my types pointless.
Use a conditional type and parameter, like this:
interface TwitterProvider { foo: number }
interface GithubProvider { foo: string }
export type UserInterface<P extends 'twitter' | 'github'> = {
id: number
username: string
photos: {
values: string
}[]
provider: P
_json: P extends 'twitter' ? TwitterProvider : P extends 'github' ? GithubProvider : {}
}
let foo: UserInterface<'twitter'> = {
id: 1,
username: 'foo',
photos: [{values: 'foo'}],
provider: 'twitter',
_json: { foo: 1 }
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.