I'm writing some wrapper functions in one of my projects (a language parser for a programming language) and found it difficult to figure out how to type something I would use in plain JS or other dynamic languages often.. Here's the use case without any typing and comments:
// This function throws if an incorrect type has been passed to it, and if not
// forward to another function:
const guardNumeric = fn => x => {
if (x.type !== AST_NODE_TYPES.AST_NUM)
throw new BlahBlahError(x.type);
return fn(x);
};
// The forwarded functions either return the ast node as is, or return the value wrapped in their body:
const identity = x => x;
const unwrap = x => x.body;
// We make guards for numbers by composing:
const ensureNum = guardNumeric(identity);
const getNumBody = guardNumeric(unwrap);
// ...There are to be dozen of other types that are wrapped similarly:
I tried all kinds of gymnastics with this but couldn't come up with anything, so I thought if some more knowledgeable TS-wizards would explain/give tips and help me grow?
What I'm aiming at would be a type signature where ensureNum could be of type:
(node: AstNode) => AstNumNode and getNumBody would be (node: AstNode) => number.. in this case the type AstNumNode always is of type that's lke:
type AstNumNode = {
type: AstNodeType;
body: number;
};