Kontrola typu interfejsu za pomocą maszynopisu
To pytanie jest bezpośrednim analogonem do sprawdzania typu klasy za pomocą maszynopisu
Muszę się dowiedzieć w czasie wykonywania, czy zmienna typu any implementuje interfejs. Oto Mój kod:
interface A{
member:string;
}
var a:any={member:"foobar"};
if(a instanceof A) alert(a.member);
Jeśli wpiszesz ten kod do maszynopisu, ostatnia linia zostanie oznaczona jako błąd, "nazwa A nie istnieje w bieżącym zakresie". Ale to nie jest prawda, nazwa istnieje w obecnym zakresie. Mogę nawet zmienić deklarację zmiennej na var a:A={member:"foobar"};
bez reklamacji od wydawcy. Po przeglądaniu sieci i znalezienie innego pytania NA więc zmieniłem interfejs do klasy, ale potem nie mogę używać literałów obiektów do tworzenia instancji.
Zastanawiałem się, jak typ A może tak zniknąć, ale spojrzenie na wygenerowany javascript wyjaśnia problem:
var a = {
member: "foobar"
};
if(a instanceof A) {
alert(a.member);
}
Nie ma reprezentacji a jako interfejsu, dlatego nie ma możliwości sprawdzenia typu runtime.
Rozumiem, że javascript jako język dynamiczny nie ma pojęcia o interfejsach. Czy jest jakiś sposób na sprawdzenie interfejsów?
Autouzupełnianie maszynopisu ujawnia, że typescript oferuje nawet metodę implements
. Jak mogę z niego korzystać ?
9 answers
Możesz osiągnąć to, co chcesz bez słowa kluczowego instanceof
, ponieważ możesz teraz napisać niestandardowy tekst:
interface A{
member:string;
}
function instanceOfA(object: any): object is A {
return 'member' in object;
}
var a:any={member:"foobar"};
if (instanceOfA(a)) {
alert(a.member);
}
Wielu członków
Jeśli musisz sprawdzić wielu członków, aby określić, czy obiekt pasuje do twojego typu, możesz zamiast tego dodać dyskryminator. Poniższy przykład jest najbardziej podstawowym i wymaga zarządzania własnymi dyskryminatorami... musisz wniknąć głębiej w wzorce, aby uniknąć powielania dyskryminatorów.
interface A{
discriminator: 'I-AM-A';
member:string;
}
function instanceOfA(object: any): object is A {
return object.discriminator === 'I-AM-A';
}
var a:any = {discriminator: 'I-AM-A', member:"foobar"};
if (instanceOfA(a)) {
alert(a.member);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-30 14:42:39
W TypeScript 1.6, user-defined type guard wykona zadanie.
interface Foo {
fooProperty: string;
}
interface Bar {
barProperty: string;
}
function isFoo(object: any): object is Foo {
return 'fooProperty' in object;
}
let object: Foo | Bar;
if (isFoo(object)) {
// `object` has type `Foo`.
object.fooProperty;
} else {
// `object` has type `Bar`.
object.barProperty;
}
I tak jak wspomniał Joe Yang: od TypeScript 2.0, możesz nawet skorzystać z tagged Union type.
interface Foo {
type: 'foo';
fooProperty: string;
}
interface Bar {
type: 'bar';
barProperty: number;
}
let object: Foo | Bar;
// You will see errors if `strictNullChecks` is enabled.
if (object.type === 'foo') {
// object has type `Foo`.
object.fooProperty;
} else {
// object has type `Bar`.
object.barProperty;
}
I działa również z switch
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-23 09:43:22
Typescript 2.0 wprowadzenie tagged union
interface Square {
kind: "square";
size: number;
}
interface Rectangle {
kind: "rectangle";
width: number;
height: number;
}
interface Circle {
kind: "circle";
radius: number;
}
type Shape = Square | Rectangle | Circle;
function area(s: Shape) {
// In the following switch statement, the type of s is narrowed in each case clause
// according to the value of the discriminant property, thus allowing the other properties
// of that variant to be accessed without a type assertion.
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-13 09:59:56
A może Strażnicy zdefiniowani przez użytkownika? https://www.typescriptlang.org/docs/handbook/advanced-types.html
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
function isFish(pet: Fish | Bird): pet is Fish { //magic happens here
return (<Fish>pet).swim !== undefined;
}
// Both calls to 'swim' and 'fly' are now okay.
if (isFish(pet)) {
pet.swim();
}
else {
pet.fly();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-16 00:37:48
Teraz jest to możliwe, właśnie wydałem ulepszoną wersję kompilatora TypeScript
, który zapewnia pełne możliwości odbicia. Można tworzyć instancje klas z ich obiektów metadanych, pobierać metadane z konstruktorów klas i sprawdzać interfejs / klasy w czasie wykonywania. Możesz to sprawdzić tutaj
Przykład użycia:
W jednym z plików maszynopisu Utwórz interfejs i klasę, które implementują go w następujący sposób:
interface MyInterface {
doSomething(what: string): number;
}
class MyClass implements MyInterface {
counter = 0;
doSomething(what: string): number {
console.log('Doing ' + what);
return this.counter++;
}
}
Teraz wydrukujmy listę zaimplementowane interfejsy.
for (let classInterface of MyClass.getClass().implements) {
console.log('Implemented interface: ' + classInterface.name)
}
Skompiluj z reflec-ts i uruchom go:
$ node main.js
Implemented interface: MyInterface
Member name: counter - member kind: number
Member name: doSomething - member kind: function
Zobacz odbicie.d. ts dla Interface
meta-type details.
aktualizacja: Pełny przykład pracy znajdziesz tutaj
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-22 09:34:51
Chciałbym zauważyć, że TypeScript nie zapewnia bezpośredniego mechanizmu dynamicznego testowania, czy obiekt implementuje konkretny interfejs.
Zamiast tego, Kod maszynopisu może używać techniki JavaScript sprawdzania, czy odpowiedni zestaw elementów jest obecny na obiekcie. Na przykład:
var obj : any = new Foo();
if (obj.someInterfaceMethod) {
...
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-11 19:18:38
TypeGuards
interface MyInterfaced {
x: number
}
function isMyInterfaced(arg: any): arg is MyInterfaced {
return arg.x !== undefined;
}
if (isMyInterfaced(obj)) {
(obj as MyInterfaced ).x;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-28 09:54:57
Oto inna opcja: moduł ts-interface-builder zapewnia narzędzie czasu kompilacji, które konwertuje interfejs TypeScript do deskryptora uruchomieniowego, a ts-interface-checker może sprawdzić, czy obiekt go spełnia.
Dla przykładu OP,
interface A {
member: string;
}
Najpierw uruchamiasz ts-interface-builder
, który tworzy nowy zwięzły Plik z deskryptorem, powiedzmy, foo-ti.ts
, którego możesz użyć w następujący sposób:
import fooDesc from './foo-ti.ts';
import {createCheckers} from "ts-interface-checker";
const {A} = createCheckers(fooDesc);
A.check({member: "hello"}); // OK
A.check({member: 17}); // Fails with ".member is not a string"
Można utworzyć jednoliniową funkcję typu strażnika:
function isA(value: any): value is A { return A.test(value); }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-26 05:26:07
To samo, co powyżej, gdzie zastosowano strażników zdefiniowanych przez użytkownika , ale tym razem z predykatem funkcji strzałki
interface A {
member:string;
}
const check = (p: any): p is A => p.hasOwnProperty('member');
var foo: any = { member: "foobar" };
if (check(foo))
alert(foo.member);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-21 12:07:31