My test code
type Config = {
id: string;
password: string;
}
type TrueTypeConfig = Config & {
emailId: number;
paymentId: number;
}
type FalseTypeConfig = Config & {
documentId: number;
buyerId: number;
}
type GetTestConfig<T extends boolean> = (type: T, id: string, password: string)
=> T extends true
? TrueTypeConfig
: FalseTypeConfig
function getTestConfig<T extends boolean> (type: T, id: string, password: string): T extends true ? TrueTypeConfig : FalseTypeConfig;
function getTestConfig (type: boolean, id: string, password: string): TrueTypeConfig | FalseTypeConfig {
const config: TrueTypeConfig | FalseTypeConfig = {
id: getRandomData(id),
password: getRandomData(password),
};
if (type) {
config.emailId = getRandomNumber(1, 100);
config.paymentId = getRandomNumber(1, 100);
} else {
config.documentId = getRandomNumber(1, 100);
config.buyerId = getRandomNumber(1, 100);
}
return config;
};
const res1 = getTestConfig(false, '1', '1'); // FalseTypeConfig
const res2 = getTestConfig(true, '1', '1'); // TrueTypeConfig
"getTestconfig" function has to return ConfigType True or False config. It depends on an argument "type". (It's working with the above test code) But const config: TrueTypeConfig | FalseTypeConfig
const config: TrueTypeConfig | FalseTypeConfig
is type error and also inside if/else codes too.
My question
const config: TrueTypeConfig | FalseTypeConfig
const config: TrueTypeConfig | FalseTypeConfig
I wanna know better way "how to define return type"
I think using a generic conditional type this way as a function return is perfectly fine. As you've noticed, the compiler is unfortunately unable to verify that a particular value inside the function implementation is assignable to such a conditional type dependent on an unspecified generic type parameter; this is the topic of microsoft/TypeScript#33912 . Until and unless that issue is addressed, you will have to shift some of the burden of type safety from the compiler to you, such as with type assertions , or, as you've done, a single-call signature overload .
As for the implementation of getTestConfig()
, you can't say that config
is a TrueTypeConfig | FalseTypeConfig
TrueTypeConfig | FalseTypeConfig
because it doesn't have enough properties to start with. At best you could say it's type Config
and then later narrow it to one of the desired types.
Instead of initializing config
in stages, which is hard for the compiler to verify, I would just use something like Object.assign()
or object spread to initialize config
all at once:
function getTestConfig<T extends boolean>(type: T, id: string, password: string): T extends true ? TrueTypeConfig : FalseTypeConfig;
function getTestConfig(type: boolean, id: string, password: string): TrueTypeConfig | FalseTypeConfig {
return {
id: getRandomData(id),
password: getRandomData(password),
...(type ?
{
emailId: getRandomNumber(1, 100),
paymentId: getRandomNumber(1, 100)
} : {
documentId: getRandomNumber(1, 100),
buyerId: getRandomNumber(1, 100)
}
)
};
}
That should compile cleanly.
The only other way I can imagine to do a return type that depends on input parameters more safely (which precludes overloads entirely) is to try to use a lookup type for the return. I tried this and it's really ugly/impenetrable and relies on coercing boolean
values to their equivalent string
via TS4.1's template literal types . I won't even include the code in the text here, since I don't recommend it. It's included in the Playground link below if you really care, and I'm happy to explain it if you want. But I'd say that a generic conditional type is probably the best solution for now.
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.