Они очень различаются по сигнатуре функции, которую они определяют.
T
, причем T
выводится (или указывается явно) при вызове функции. Рассмотрим следующие объявления:
declare const fn: FnWithRequiredParam<number>
declare const genericFn: FnWithParamInferred;
// T was fixed on declaration
fn(1) // ok
fn("1") // err
// T is decded by the caller
genericFn(1) // ok T is number for this call
genericFn("1") // ok T is string for this call
genericFn<number>("1") // err T was specified as number but string was passed in
Причиной ошибки, которую вы получаете, является то, что вы пытаетесь назначить функцию с параметром number
для функции, которая должна принимать параметр любого типа T
, с T
, который должен определять вызывающий функции. Только универсальная функция может соответствовать типу FnWithParamInferred
var f: FnWithParamInferred = <T>(a: T) => { console.log(a) }
Я думаю, что вы действительно хотите, чтобы иметь возможность опустить явный аргумент типа из объявления переменной и сделать его вывод на основе назначенного значения к этому. Typescript не поддерживает это. Если вы определите аннотацию типа для переменной, то для нее не будет никакого вывода.
Вы можете вообще опустить аннотацию типа, чтобы позволить компилятору выводить тип функции:
var f = (a: number) => { console.log(a) } // inferred as (a: number) => void
Или вы можете определить универсальную вспомогательную функцию для вывода T
, но ограничить сигнатуру функции основан на FnWithRequiredParam
function createFunction<T>(fn: FnWithRequiredParam<T>) {
return fn;
}
var f = createFunction((a: number) => { console.log(a) }) // inferred as FnWithRequiredParam<number>
Используйте словарь, который отображает имена тега к обработчику тегов.
Вы хотите условное выражение замены с полиморфизмом . Примерно:
string getContent(const string& name) {
myType obj = factory.getObjForName(name);
obj.doStuff();
}
, где doStuff перегружается.
Вы рассмотрели XSLT? Это очень хорошо подходит для такого рода вещи. Я разработал систему управления контентом, которая сделала ту же самую вещь и нашла, что XSLT был очень эффективным. Синтаксический анализатор делает большую работу для Вас.
ОБНОВЛЕНИЕ: комментарий Steven поднимает важный вопрос - Вы захотите, чтобы Ваши шаблоны были допустимым XHTML, если Вы решите пойти путем XSLT. Также - я использовал бы другой разделитель для Ваших заменяющих маркеров. Что-то менее вероятно для появления естественно. Я использовал #! PLACEHOLDER#! в моем CMS.
я объединю 3 идеи:
switch(){}
. setup()
метод к каждому классу обработчика, который добавляет себя (или новый экземпляр класса) к словарю. объяснение немного:
static
dict и методы для регистрации экземпляра в селекторной строке. setup()
метод регистрирует себя в dictВместо парсинга, попытались просто читать шаблон в строку и затем просто выполнить замены.
fileContents = fileContents.Replace("%title%", page->getTitle());
fileContents = fileContents.Replace("%color%", getBodyColor());
Как "Дядя" Bob Martin, упомянутый в предыдущем podacast с Joel и Jeff, в значительной степени, что-либо, что Вы придумываете, собирается по существу воспроизвести большой оператор переключения.
, Если Вы чувствуете себя лучше, реализовывая одно из решений, выбранных выше, это прекрасно. Это может сделать Ваш код более симпатичным, но под покрытиями, это чрезвычайно эквивалентно.
важная вещь состоит в том, чтобы гарантировать, что существует только один экземпляр Вашего большого оператора переключения. Ваш оператор переключения или словарь должны определить, какой класс обрабатывает этот тег, и затем последующие определения должны быть обработаны с помощью полиморфизма.