Skip to content

Instantly share code, notes, and snippets.

@geovanisouza92
Last active December 14, 2017 20:10
Show Gist options
  • Save geovanisouza92/39f76f2f9e80ef9c1a42ecb2b625b4ec to your computer and use it in GitHub Desktop.
Save geovanisouza92/39f76f2f9e80ef9c1a42ecb2b625b4ec to your computer and use it in GitHub Desktop.
--strictFunctionTypes generates errors with generic functions
type Direction = keyof IDirectionOptions;
interface IDirectionOptions {
"horizontal": { foo: number; };
"vertical": { bar: string; };
"diagonal": { baz: boolean; };
}
// This structure works
type FnOk<D extends Direction> = () => ResultOk<D>;
type ResultOk<D extends Direction> =
{ kind: "invalid", err: Error }
| { kind: "valid", data: IDirectionOptions[D] }
;
function horizontalOk(): ResultOk<"horizontal"> {
return { kind: "valid", data: { foo: 123 } };
};
function verticalOk(): ResultOk<"vertical"> {
if (Math.random() > 0.5) {
return { kind: "valid", data: { bar: "foo" } };
}
return { kind: "invalid", err: new Error("LOL") };
}
const horizontalOkConst: FnOk<"horizontal"> = horizontalOk;
const verticalOkConst: FnOk<"vertical"> = verticalOk;
function selectOk<D extends Direction>(direction: Direction): FnOk<D> {
switch (direction) {
case "horizontal": return horizontalOk;
case "vertical": {
const v = verticalOk();
if (v.kind === "valid") {
v.data.bar;
}
return verticalOk;
}
case "diagonal": return () => ({ kind: "invalid", err: new Error("lol") });
}
}
// This structure doesn't
type FnErr<D extends Direction> = () => ResultErr<D>;
type ResultErr<D extends Direction> =
{ kind: "invalid", err: Error }
| { kind: "valid", data: IData<D> }
;
interface IData<D extends Direction> {
value: IDirectionOptions[D];
}
function horizontalErr(): ResultErr<"horizontal"> {
return { kind: "valid", data: { value: { foo: 123 } } };
};
function verticalErr(): ResultErr<"vertical"> {
if (Math.random() > 0.5) {
return { kind: "valid", data: { value: { bar: "foo" } } };
}
return { kind: "invalid", err: new Error("LOL") };
}
const horizontalErrConst: FnErr<"horizontal"> = horizontalErr;
const verticalErrConst: FnErr<"vertical"> = verticalErr;
function selectErr<D extends Direction>(direction: Direction): FnErr<D> {
switch (direction) {
case "horizontal": return horizontalErr; // Error here
case "vertical": {
const v = verticalErr();
if (v.kind === "valid") {
v.data.value.bar;
}
return verticalErr; // Error here
}
case "diagonal": return () => ({ kind: "invalid", err: new Error("lol") });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment