Consider the following generic interface:
interface Extractor<T> {
extractCandidate(): T;
process(candidate: T): T;
}
Conceptually, each Extractor implementation is responsible for extracting a particular kind of object from some datasource. The consumer of the Extractor can extract a candidate object using extractCandidate() or, given any candidate, perform some further processing on it to get a more refined version of the object using process().
Now, let's say I implement an Extractor for a class MyClass, like so:
class MyClass {
a: string;
b: string;
}
class MyExtractor implements Extractor<MyClass> {
extractCandidate() {
//Some dummy logic
return new MyClass();
}
process(candidate) {
//Some dummy logic
let res = new MyClass();
res.a = candidate.a;
return res;
}
}
Now let's say I instantiate MyExtractor and use it:
let myExtractor = new MyExtractor();
let processed = myExtractor.process('blah');
Question 1: Why does this not generate a compile-time error? Based on the definition of the Extractor interface, I would expect that the compiler would not allow me to call myExtractor.process() with anything but an instance of MyClass, or at least with something that is structurally compatible.
Question 2: How can I enforce the desired behavior? Do I just need to assert that the candidate parameter of MyExtractor.process() is of type MyClass?
I suspect this has something to do with TypeScript's structural typing system but, after reading some related questions and the FAQ, I'm still not sure how it specifically applies here.
My Typescript version is 2.1.4.