Тест на совместимость типов
Поддерживает ли Typescript прямой тест на совместимость структурных типов?
C# поддерживает is
Оператор и типы поверхности IsAssignableFrom(object instance)
if (foo is SomeType) ...
if (SomeType.IsAssignableFrom(foo)) ...
Есть ли какой-нибудь прямой способ выполнить такую проверку в Typescript или мне нужно проверять каждого из необходимых членов?
instanceof
вероятно, подойдет для рассматриваемого случая, но не учитывает структурную совместимость, вместо этого проверяя цепочку прототипов.
Да, да, я знаю, Typescript instanceof
прямо эквивалентно C# is
оператор. Но я начал с определения структурной типизации.
Может быть, я должен положить метод кряка Object
1 ответ
Я считаю, что соответствующий ответ здесь
Нет, но!
Так что просто для того, чтобы избавиться от этого, информация о типах Typescript существует только во время компиляции. Нет способа сделать проверку структурного равенства во время выполнения. Конечно, вы можете выполнить эту проверку во время компиляции, но это просто называется присваиванием, и, вероятно, не тем, о чем вы спрашиваете.
Короче говоря, вы должны исследовать требуемых участников (как правило), но есть несколько способов проявить смекалку.
Начиная с Typescript 1.6, язык поддерживает определяемые пользователем средства защиты типов
Это замечательные удобные функции и способ безопасного снижения / уточнения / уточнения типа (в зависимости от предпочитаемой вами терминологии). Вы можете вручную проверить наличие определенных типов, если хотите обычными способами (.hasOwnProperty
и тому подобное), по моему опыту, они более эффективны как способы отправки сообщений по типам сообщений. В большинстве систем передачи сообщений у вас может быть свойство типа. Вы можете определить функцию
function isConfigGetMsg(msg: BaseMessage): msg is ConfigGetMsg {
return msg.name === MsgTypes.CONFIG_GET_MSG;
}
//and use it as
if (isConfigGetMsg(msg)){
console.log(msg.key); //key being a ConfigGetMsg only value
}
и это будет хорошо, пока ваши сообщения правильно сформированы. Хотя, как вы можете видеть, вам нужно проверить на конкретную информацию. Если вы хотите более общий подход, это не так.
Как вы упомянули, вы можете проверить каждого из необходимых участников. Вы можете сделать это немного проще для себя, используя предыдущую технику, чтобы создать что-то вроде этого:
interface One {
a: number
}
interface Two extends One {
b: string
}
function isAssignableTo<T>(potentialObj:Object, target:T) : potentialObj is T {
return Object.keys(target).every(key => potentialObj.hasOwnProperty(key))
}
let a: Object = {
a: 4,
b: 'hello'
};
let b: Two = undefined;
if(isAssignableTo(a, b)) {
b = a;
}
isAssignableTo
функция является ключевым моментом здесь. Направление, в котором должны быть параметры, является дискуссионным, но также не имеет значения, поэтому размещайте их по своему усмотрению. Это не идеальное решение. Возможно, вы захотите, чтобы вещи можно было назначать на основе только нефункциональных свойств, например, подразумевающего состояния, а не общей функциональности. Вы можете попытаться расширить проверку, чтобы учесть это, но есть и подводные камни.
Мне жаль говорить, что я верю, что единственный "верный" ответ - это тот, который пока не жизнеспособен. Если вы работаете с классами, вы можете использовать декораторы для сбора метаданных о вашем приложении, включая информацию о типах, которая впоследствии может быть использована для отражения / проверки. Вы можете создать свои собственные декораторы для этого, но вы также можете использовать собственную генерацию метаданных машинописного текста для свойств класса. что вы можете включить с помощью флага tsconfig.
Это предполагает наличие метаданных отражения api. Вам нужно будет использовать это, чтобы извлечь эту информацию. Затем вы можете переписать функцию isAssignableTo с более ранней версии, чтобы отработать метаданные. Если я правильно помню, это все еще страдает от проблемы, что типы хранятся в виде строк, и если у вас есть подтипы, они не будут совпадать.
Во всяком случае, я надеюсь, что это помогает. Извините, я не могу дать вам простое да. Зная мою удачу, вы на самом деле просто искали назначение ;)
,