0

Is there any way to have a function that only takes certain functions as parameters?

This is what I want to do:

function foo(str: string): string
function bar(str: string): string

function baz(f: foo | bar): any

I know I could do this: function baz(f: (string) => string): any, but that's not quite what I'm looking for here. Also, I don't really have a purpose for this question, just asking out of curiosity.

1 Answer 1

1

You can reuse the signature of a specific function as a parameter to another function using typeof

function foo(str: string): string { return ""}
function baz(f: typeof foo): any {}

But if you want to limit the parameter to just those two specific function, there is no way to express that in typescript (typescript generally goes by structure not by nominal declarations even for objects)

You might be able to do something using specially crafted branded types:

function createBrandedFunction<T, B extends new(...a: any[]) => any>(fn: T, brand: ()=> B) : T & { __brand: B } {
    return fn as any
}


const foo = createBrandedFunction(
    function (str: string): string { return ""}, 
    ()=> class { private p: any}) // we just use a class with a private field to make sure the brand is incompatible with anything else

const bar = createBrandedFunction(
    function (str: string): string { return ""}, 
    ()=> class { private p: any}) // even a class with the same private is not compatible

function baz(f: typeof foo): any {}
baz(foo) // ok
baz(bar) // err
baz((s)=> "") // err
Sign up to request clarification or add additional context in comments.

3 Comments

Using Typescript 3.4.3 I get an error in the assignment of foo and bar. The error says "Property 'p' of exported class expression may not be private or protected.ts(4094)". If I remove the private this error is removed but then baz(bar) gets accepted and no error is thrown. The code is just copied and pasted from you example.
@Picci If you have declaration generation turned on, this error might occur with class expressions. You can use a regular class or use something else as the brand
great, I actually had declaration true. Switching it to false removed the error and led the compiler to detect the error on baz(bar). If I try though to use regular classes, e.g. class A {p: any} and class B {p: any}, I do not get the compiler to detect the error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.