microsoft / microsoft/TypeScript

Define a global context in a function signature, to enforce typing.

Open
#43,434 3 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Awaiting More Feedback Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

🔍 Search Terms

  • global context
  • enforce global variable

✅ Viability Checklist

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

I would like to be able to define that a method can have access to a custom global environment, within the function.
It can be implemented exactly as the this typing.
the main issue is to find a reserved keyword, or syntax to do that.

📃 Motivating Example

Improve puppeteer extensions.

💻 Use Cases

This feature is most useful when we write a code that will be executed in another javascript environment like:

  • writing code that will be injected into a browser (like puppeteer)
  • writing a code that will be called in a nodejs worker.

if I use puppeteer-jquery to enable jQuery into my browser.

I can now write:

import puppeteer from 'puppeteer';
import { PageEx, pageExtend } from 'puppeteer-jquery'

interface Items{ item: string; } 

var jQuery: JQueryStatic; // declare that a jQuery object exists

const browser = puppeteer.launch(option); // start a browser
const page = await browser.newPage(); // create a tab
const page2 = pageExtend(page0); // inject jQuery to the page
const data = (await page.jQuery('div.entry').map((id: number, elm: HTMLElement) => {
    const impData = jQuery(elm).find('.important');
    return { item }
}).pojo()) as Items[];

the jQuery object is available inside the browser but not inside the nodeJS, this code works, but I need to add a dirty var jQuery: JQueryStatic; at the top of the file
currently, the jQuery map method of page signature is:

    map(mapping: (index: number, element: any) => any): PJQueryHybrid;

with a feature to define a custom environment, this code will be replaced by:

import puppeteer from 'puppeteer';
import { PageEx, pageExtend } from 'puppeteer-jquery'

interface Items{ item: string; }

const browser = puppeteer.launch(option); // start a browser
const page = await browser.newPage(); // create a tab
const page2 = pageExtend(page0); // inject jQuery to the page
const data = (await page.jQuery('div.entry').map((id: number, elm: HTMLElement) => {
    const impData = jQuery(elm).find('.important');
    return { item }
}).pojo()) as Items[];

and, the jQuery method of page signature will be something like:

interface JQPage{
    navigator: Navigator;
    jQuery: JQueryStatic;
    // ...
}
// this type is extracted from puppeteer-jquery, it's strange but it is correct.
type PJQueryHybrid = PJQuery & Promise<PJQuery>

interface Page {
    jQuery(global: JQPage, this: unknow, selector: string): PJQuery;
}

interface PJQuery {
    // current
    // map(callback: (this: TElement, index: number, element: TElement) => any): PJQueryHybrid;
    // new version 
    map(callback: (global: JQPage, this: TElement, index: number, element: TElement) => any): PJQueryHybrid;
}


proposition:

The this parameter named is already reserved and must be placed in a first position.
if a global parameter is added before the this parameter it will be interpreted as a global environment, and so will not need reserving a new reserved keyword.

The tsConfig.json can be used to define if the code is used inside a nodeJS or a browser, but when we mixte the two destinations in the same code... it can not be used.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names no files or tests; start by reviewing TypeScript's existing handling of the reserved this parameter and the proposed callback signatures. Done would require an agreed syntax and type-checking behavior for a custom global context, followed by corresponding compiler tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.