#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}
, я не получаю компилятор для обнаружения ошибки.