Esta questão é o analogon direto da verificação de tipo de classe com o TypeScript
Preciso descobrir em tempo de execução se uma variável do tipo any implementa uma interface. Aqui está o meu código:
interface A{
member:string;
}
var a:any={member:"foobar"};
if(a instanceof A) alert(a.member);
Se você digitar esse código no parque de texto datilografado, a última linha será marcada como um erro "O nome A não existe no escopo atual". Mas isso não é verdade, o nome existe no escopo atual. Posso até alterar a declaração da variável para var a:A={member:"foobar"};
sem queixas do editor. Depois de navegar na web e encontrar a outra pergunta no SO, mudei a interface para uma classe, mas não consigo usar literais de objeto para criar instâncias.
Gostaria de saber como o tipo A poderia desaparecer assim, mas uma olhada no javascript gerado explica o problema:
var a = {
member: "foobar"
};
if(a instanceof A) {
alert(a.member);
}
Não há representação de A como uma interface, portanto, nenhuma verificação de tipo de tempo de execução é possível.
Eu entendo que o javascript como uma linguagem dinâmica não tem conceito de interfaces. Existe alguma maneira de digitar check para interfaces?
O preenchimento automático do playground de texto datilografado revela que o texto datilografado ainda oferece um método implements
. Como posso usá-lo?
Respostas:
Você pode conseguir o que deseja sem a
instanceof
palavra - chave, já que pode escrever protetores de tipo personalizados agora:Muitos membros
Se você precisar verificar vários membros para determinar se um objeto corresponde ao seu tipo, adicione um discriminador. O exemplo abaixo é o mais básico e exige que você gerencie seus próprios discriminadores ... você precisará se aprofundar nos padrões para garantir que você evite duplicados discriminadores.
fonte
isInstanceOfA(instantiatedB)
retornar true, mas que queiraisInstanceOfB(instantiatedA)
retornar false. Para que isso ocorra, o discriminador de B não precisa ser 'I-AM-A'?No TypeScript 1.6, a proteção de tipo definida pelo usuário fará o trabalho.
E, como Joe Yang mencionou: desde o TypeScript 2.0, você pode tirar vantagem do tipo de união com tags.
E isso também funciona
switch
.fonte
object is type
eobject instanceof class
é que, o TypeScript é estrutural, importa apenas a "forma", e não de onde um objeto obteve a forma: um objeto simples ou uma instância de uma classe, isso não importa.type
propriedade Nesse caso, funciona. Esse exemplo não mostra esse fato.typescript 2.0 introduzir união marcada
Recursos do Typecript 2.0
fonte
E quanto às proteções de tipo definidas pelo usuário? https://www.typescriptlang.org/docs/handbook/advanced-types.html
fonte
(pet as Fish).swim !== undefined;
funcionou.Agora é possível, acabei de lançar uma versão aprimorada do
TypeScript
compilador que fornece recursos completos de reflexão. Você pode instanciar classes de seus objetos de metadados, recuperar metadados de construtores de classe e inspecionar interface / classes em tempo de execução. Você pode conferir aquiExemplo de uso:
Em um dos seus arquivos datilografados, crie uma interface e uma classe que a implemente da seguinte maneira:
agora vamos imprimir algumas da lista de interfaces implementadas.
compile com o reflec-ts e inicie-o:
Veja reflection.d.ts para
Interface
detalhes do tipo meta.UPDATE: Você pode encontrar um exemplo de trabalho completo aqui
fonte
implements
mas queria reconhecer o seu empenho e não queria ser mau :-)igual ao descrito acima, onde os protetores definidos pelo usuário foram usados, mas desta vez com um predicado de função de seta
fonte
Aqui está outra opção: o módulo ts-interface-builder fornece uma ferramenta em tempo de construção que converte uma interface TypeScript em um descritor de tempo de execução, e o ts-interface-checker pode verificar se um objeto a satisfaz.
Para o exemplo do OP,
Você executaria primeiro o
ts-interface-builder
que produziria um novo arquivo conciso com um descritor, por exemplofoo-ti.ts
, que você possa usar assim:Você pode criar uma função de proteção de tipo de uma linha:
fonte
Gostaria de salientar que o TypeScript não fornece um mecanismo direto para testar dinamicamente se um objeto implementa uma interface específica.
Em vez disso, o código TypeScript pode usar a técnica JavaScript para verificar se um conjunto apropriado de membros está presente no objeto. Por exemplo:
fonte
for (element in obj) {}
) para verificar se os dois objetos têm os elementos semelhantes de tipos semelhantes.TypeGuards
fonte
Com base na resposta de Fenton , aqui está minha implementação de uma função para verificar se um dado
object
tem as chaves e uminterface
total ou parcialmente.Dependendo do seu caso de uso, também pode ser necessário verificar os tipos de cada uma das propriedades da interface. O código abaixo não faz isso.
Exemplo de uso:
fonte
fonte
Como o tipo é desconhecido no tempo de execução, escrevi o código da seguinte maneira para comparar o objeto desconhecido, não contra um tipo, mas contra um objeto do tipo conhecido:
Aqui está o código (independente de interface) que eu uso para uma comparação profunda:
Abaixo está um exemplo de como eu o uso.
Neste exemplo, espero que o JSON contenha uma matriz de tuplas, da qual o segundo elemento é uma instância de uma interface chamada
User
(que possui dois elementos opcionais).A verificação de tipo do TypeScript garantirá que meu objeto de amostra esteja correto, e a função assertTypeT verifica se o objeto desconhecido (carregado de JSON) corresponde ao objeto de amostra.
Você pode chamar uma verificação como esta na implementação de uma proteção de tipo definida pelo usuário.
fonte
Você pode validar um tipo TypeScript em tempo de execução usando ts-validate-type , assim: (embora exija um plug-in Babel):
fonte