Использование определенных функций в качестве параметров в TypeScript

#typescript #function #parameters

#машинописный текст #функция #параметры #typescript

Вопрос:

Есть ли какой-нибудь способ создать функцию, которая принимает только определенные функции в качестве параметров?

Это то, что я хочу сделать:

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

function baz(f: foo | bar): any
  

Я знаю, что мог бы сделать это: function baz(f: (string) => string): any , но это не совсем то, что я здесь ищу. Кроме того, у меня на самом деле нет цели для этого вопроса, я просто спрашиваю из любопытства.

Ответ №1:

Вы можете повторно использовать сигнатуру определенной функции в качестве параметра для другой функции, используя typeof

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

Но если вы хотите ограничить параметр только этими двумя конкретными функциями, нет способа выразить это в typescript (typescript обычно использует структуру, а не номинальные объявления даже для объектов)

Возможно, вы сможете что-то сделать, используя специально созданные фирменные типы:

 function createBrandedFunction<T, B extends new(...a: any[]) => any>(fn: T, brand: ()=> B) : T amp; { __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
  

Комментарии:

1. Используя Typescript 3.4.3, я получаю ошибку при назначении foo и bar . Ошибка гласит: «Свойство ‘p’ экспортируемого выражения класса не может быть закрытым или защищенным.ts (4094)» . Если я удалю private эту ошибку, она будет удалена, но затем baz(bar) будет принята, и ошибка не будет выдана. Код просто скопирован и вставлен из вашего примера.

2. @Picci Если у вас включена генерация объявлений, эта ошибка может возникнуть с выражениями класса. Вы можете использовать обычный класс или использовать что-то другое в качестве бренда

3. отлично, я действительно сделал заявление правдивым. Переключение его на false устранило ошибку и привело к включению компилятора для обнаружения ошибки baz(bar) . Если я попытаюсь использовать обычные классы, например class A {p: any} , и class B {p: any} , я не получаю компилятор для обнаружения ошибки.