Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
143 views
in Technique[技术] by (71.8m points)

javascript - Type annotation for `this` keyword in Typescript

I have a standalone function that's meant to use the context provided by Function.prototype.call.

For example:

function foo () {
    return this.bar;
}

> foo.call({bar: "baz"})
baz

Is there a way to provide a Typescript type annotation for the this keyword in this scenario?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's a bit ugly, in my opinion.

First of all, you can use the special this parameter syntax to identify the type of object you expect this to be:

function foo (this: {bar: string}) {
    return this.bar; // no more error
}

which helps if you call it directly:

foo(); // error, this is undefined, not {bar: string}

var barHaver = { bar: "hello", doFoo: foo };
barHaver.doFoo(); // acceptable, since barHaver.bar is a string

var carHaver = { car: "hello", doFoo: foo };
carHaver.doFoo(); // unacceptable, carHaver.bar is undefined

But you want to use foo.call(). Unfortunately the Function.prototype.call() typing in TypeScript won't really enforce this restriction for you:

foo.call({ bar: "baz" }); // okay, but
foo.call({ baz: "quux" }); // no error, too bad!

Merging something better into TypeScript's Function declaration caused me problems, (First point of ugliness; you will need to cast foo to something) so you can try something like this:

interface ThisFunction<T extends {} = {}, R extends any = any, A extends any = any> {
  (this: T, ...args: A[]): R;
  call(thisArg: T, ...args: A[]): R;
}

A ThisFunction<T,R,A> is a function with a this of type T, a return value of type R, and a rest argument of type A[]. (Second point of ugliness: you can't easily specify multiple arguments of different types in a way that will be enforced by the type system.)

You can then cast foo to ThisFunction<{ bar: string }, string>, (Third point of ugliness: the type system just will not infer this types) and then finally use call():

(<ThisFunction<{ bar: string }, string>>foo).call({ bar: "baz" }); // okay, and
(<ThisFunction<{ bar: string }, string>>foo).call({ baz: "quux" }); // error, hooray!

Hope that helps!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...