I want to return a promise if the user set true for async.
is seems typescript will always take the type from Create interface. how will I create a type that will be used to define the return type?
interface Create<T> {
options: {
async: boolean;
};
properties: T;
}
type Return<T extends Create<any>> = T["options"]["async"] extends true ? Promise<boolean> : boolean;
const create = <T>(value: Create<T>): Return<Create<T>> => {
return true;
};
interface User {
username: string;
password: string;
}
// is not promise
create<User>({
options: {
async: true,
},
properties: {
username: "",
password: "",
},
});
CodePudding user response:
This is the best I can do. I don't like having to use a type assertion on the return, but I couldn't find a way around it.
interface Create<T> {
options: {
async: boolean;
};
properties: T;
}
type Return<T> = T extends { options: { async: true } } ? Promise<boolean> : boolean;
const create = <T extends Create<any>>(value: T): Return<T> => {
if (value.options.async === true) {
return new Promise<boolean>((resolve) => resolve(true)) as Return<T>;
}
return true as Return<T>;
};
interface User {
username: string;
password: string;
}
create<Create<User>>({
options: {
async: true,
},
properties: {
username: '',
password: '',
},
});
CodePudding user response:
You just need one additional generic type parameter for the async
option so that you can use it to infer the correct return type:
type Create<Properties, IsAsync extends boolean> = {
options: { async: IsAsync };
properties: Properties;
};
type CreateResult<IsAsync extends boolean> = IsAsync extends true ? Promise<boolean> : boolean;
declare function create <Properties, IsAsync extends boolean>(
input: Create<Properties, IsAsync>,
): CreateResult<IsAsync>;
type User = {
username: string;
password: string;
};
declare const userProps: User;
// Using the literal `true` results in a Promise:
const r1 = create({ options: {async: true}, properties: userProps });
//^? const r1: Promise<boolean>
// Using the literal `false` results in a boolean:
const r2 = create({ options: {async: false}, properties: userProps });
//^? const r2: boolean
// Using an indeterminate boolean variable results in a union of either possibility:
declare let isAsync: boolean;
const r3 = create({ options: {async: isAsync}, properties: userProps });
//^? const r3: boolean | Promise<boolean>
Update in response to your comment:
declare function create <IsAsync extends boolean>(
input: {
options: { async: IsAsync };
properties: unknown;
},
): IsAsync extends true ? Promise<boolean> : boolean;