I have a function that takes an object as an argument. When a property of that input is a given value, I want to specify the return type as being one or the other. I assume this requires conditional types, but I'm struggling with the syntax to access the property of a given interface.
What I currently have is below:
enum FileAcl {
private = 'private',
public = 'public',
}
interface UploadOpts {
someval: string;
acl: FileAcl;
}
interface PrivateAclResponse {
acl: FileAcl.private;
key: string;
}
interface PublicAclResponse {
acl: FileAcl.public;
file: string;
}
const uploadFile = async (opts: UploadOpts):
Promise<PublicAclResponse | PrivateAclResponse> => {
const { acl } = opts;
if (opts.acl === FileAcl.public) return { file: 'file', acl }
return { key: 'key', acl }
}
I did try the following, but I'm clearly wrong so any guidance would be much appreciated.
enum FileAcl {
private = 'private',
public = 'public',
}
interface UploadOpts {
someval: string;
acl: FileAcl;
}
interface PrivateAclResponse {
acl: FileAcl.private;
key: string;
}
interface PublicAclResponse {
acl: FileAcl.public;
file: string;
}
// assuming here that ts can match the common properties
type PublicOrPrivate<T extends UploadOpts> = T extends PublicAclResponse
? PublicAclResponse
: PrivateAclResponse;
const uploadFile = async (
opts: UploadOpts
): Promise<PublicOrPrivate<UploadOpts>> => {
const { acl } = opts;
if (opts.acl === FileAcl.public) return { file: 'file', acl }
return { key: 'key', acl }
}
TIA
You can indeed use a Conditional Type. But additionally a generic parameter is needed for the condition. Unfortunately, TypeScript doesn't seem to be able to narrow
opts
to eitherPublicAclResponse
orPrivateAclResponse
which means we need to assert the return type.TypeScript Playground