question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add feature to re-declare variable

See original GitHub issue

Search Terms

redeclare variable, re-declare variable, augment variable, merge variable declaration, declaration override

Suggestion

define a redeclare keyword which allows re-declaration of a typed variable. e.g.

redeclare var foo: {
  prop: string
};

Use Cases

When an external library declares a variable, e.g.

declare var x: {
  prop: string;
};

The redeclare keyword can be used somewhere else to override the declaration:

redeclare var x: number;

or augment it:

redeclare var x: typeof x & {
  augmentedProp: number;
}

This would allow to type the pure JavaScript case of:

// lib.js
var x = {
  prop: "foo"
};

// app.js
x.augmentedProp = 10;

console.log(x.prop, x.augmentedProp);

Examples

declare var URLSearchParams: {
    prototype: URLSearchParams;
    new(init?: string[][] | Record<string, string> | string | URLSearchParams): URLSearchParams;
    toString(): string;
};

defined in lib.dom.d.ts

to extend the variable with additional static methods to URLSearchParams is not possible currently (see here).

The feature can be used in the following way:

redeclare var URLSearchParams: typeof URLSearchParams & {
  fromObject(obj: object): URLSearchParams;
};

if (!URLSearchParams.fromObject) {
  URLSearchParams.fromObject = function(obj: object): URLSearchParams { /* implementation */  }
}

Checklist

My suggestion meets these guidelines:

  • 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, etc.)
  • This feature would agree with the rest of TypeScript’s Design Goals.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:2
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
dguttman-jacadacommented, Apr 6, 2020

@DanielRosenwasser my answer would be:

  1. depending on context of execution flow . Even today, typescript knows that for:
    function foo(input: string | number): string {
      if (typeof input === "string") {
        return input; // here input is string
      } else {
        return number.toString(); // here input is number
      }
    } 
    
    so in your example, hello would end up a string (if the code is processed sequentially)
  2. It makes sense for the redeclare to be scoped, so if the variable was redeclared within a function body (or any other relevant scope), the redeclaration would be valid for the scope of the function body. e.g for an express app:
    app.get("/", (req, res, next) => {
      redeclare req: typeof req & { myProp: string };
      req.myProp = Guid.generate();
      asyncOp((res) => {
        res.send(res.req.myProp);
      });
    });
    
    req.myProp = ""; // error - req does not have a 'myProp' property
    
  3. in JavaScript it is also possible to do:
    // file1.js
    var hello = 123; // essentially declare it as a number, would work with declare var hello: string | number;
    
    // file2.js
    var hello = "foo"; // essentially declare it as a string, would work with declare var hello: string | number;
    
    // file3.js
    var hello = false; // essentially declare it as a boolean, would *not* work with the above and would need to be redeclared - in most cases: redeclare var hello: typeof hello | boolean;
    
    currently there is no way to describe this with TypeScript
0reactions
sdrsdrcommented, Oct 13, 2022

redeclare can have other benefits:

I have a “header” type of interface:

export interface api_msg_t {
	a:string;
	devid:string;
}

function is_api_msg(m:any) :m is api_msg_t {
	return (
		m && typeof(m)=="object" && typeof(m.a)=='string' && typeof(m.devid)=='string'
	)
}

I want to have extended interface:

interface api_node_online_t extends api_msg_t {
	a:"onl";
	nid:number;
	state:node_state;
}
function is_api_node_online(m:api_msg_t) : m is api_node_online_t {
	return (m.a=='onl' && typeof(m.nid)=="number" && is_node_state(m.state));
}

if there is no inex type in api_msg_t the typeguard is_api_node_online fails to transpile as m.nid does not exist in api_msg_t. But adding index in the api_msg_t propagates it to api_node_online_t that is undesirable. if we can do

function is_api_node_online(m:api_msg_t) : m is api_node_online_t {
	redaclare m as api_msg_t & {[index:string]:unknonw};
	return (m.a=='onl' && typeof(m.nid)=="number" && is_node_state(m.state));
}

It will allow for elegant and typesafe solution.

We can easily mimic this behavior with

interface api_msg_indexed_t extends api_msg_t {
	[index:string]:nknown;
}

function is_api_msg_indexed(m:api_msg_t):m is api_msg_indexed_t:{
	return true;
}

function is_api_node_online(m:api_msg_t) : m is api_node_online_t {
	if (!api_msg_indexed(m)) return;
	return (m.a=='onl' && typeof(m.nid)=="number" && is_node_state(m.state));
}

but this results in unnecessary JS code emitted and ran

Read more comments on GitHub >

github_iconTop Results From Across the Web

how to redeclare a variable in different datatypes in c
No, you cannot redefine a variable with different types within the same scope. Although, there is one possible alternative.
Read more >
Understand variables in canvas apps - Power Apps
All variables are created implicitly when they appear in a Set, UpdateContext, Navigate, Collect, or ClearCollect function. To declare a ...
Read more >
Declare a variable | Help - Zoho Deluge
Assigning a new value to a variable declared earlier will overwrite the existing value. · Variables need not be declared initially before assigning...
Read more >
Documentation: 15: 43.3. Declarations - PostgreSQL
%TYPE provides the data type of a variable or table column. You can use this to declare variables that will hold database values....
Read more >
Procedural language | BigQuery - Google Cloud
You do not need to declare system variables, but you can set any of them that ... add a row for Ulysses, using...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found