Reputation: 520
In the following example, is it possible to make parse()
available only if key
was passed using TypeScript?
// SOURCE CODE:
interface Input {
key?: string;
data: Record<string, string>;
}
interface Options {
parse: (x: string) => void;
}
type HelperFunc = (options: Options) => void;
const myFunc = (input: Input, helper: HelperFunc): void => {
// How to implement this such that if key is passed, only then make `parse()` available?
// CONSTRAINT: I don't want to make `parse()` an optional field because user will call
// it multiple times and I don't want them to do `parse?.()` all the time.
if (input.key) {
helper({ parse: (x) => `${x} parsed using ${input.key}` })
} else {
helper({}); // currently throws valid TypeScript error
}
// do something with input.data
};
// EXPECTED USAGE:
myFunc({
key: "my-key",
data: {
"someData": "someValue"
}
}, ({ parse }) => {
// No TypeScript errors
parse("parse this");
parse("parse that");
parse("parse this and that");
});
// mentioning parse should throw TypeScript error because key was not passed
myFunc({
data: {
"someData": "someValue"
}
}, ({ parse }) => {
/* either throw error here when calling or while de-structuring above */
parse("parse this");
});
I'm just wondering if this is possible using TypeScript.
Upvotes: 0
Views: 35
Reputation: 2742
You can achieve this by overloading the myFunc
function.
First declare two types of interfaces that will be used for each of your parameters. First - ones that have no key:
interface InputData {
data: Record<string, string>;
}
type EmptyHelperFunc = (options: {}) => void;
And ones where all data is present:
type Input = {
key?: string;
} & InputData;
interface Options {
parse: (x: string) => void;
}
type HelperFunc = (options: Options) => void;
The overload type can then be declared and used as follows:
type MyFuncOverload = {
(input: InputData, helper: EmptyHelperFunc): void
(input: Required<Input>, helper: HelperFunc): void
}
const myFunc: MyFuncOverload = (input: Input, helper: HelperFunc): void => {
Playground link.
Upvotes: 1