Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot access name of function or class in a type-safe way #2076

Closed
mblinsitu opened this issue Feb 19, 2015 · 13 comments
Closed

Cannot access name of function or class in a type-safe way #2076

mblinsitu opened this issue Feb 19, 2015 · 13 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@mblinsitu
Copy link

The property name of function does not seem to be available in Typescript:

function foo() {…}
foo.name; // 'foo'

error TS2339: Property 'name' does not exist on type '() => string'.

I can declare an interface but it requires a cast:

interface F {
    (...rest): any;
    name: string
}

(<F>foo).name;

Is there a better way? Shouldn't Typescript know about the predefined properties of functions?

While I'm at it, the same issue comes up with classes: the name of the constructor is the name of the class, so in plain Javascript you could get the name as above, but it does not work in Typescript:

class A { …}
A.name

error TS2339: Property 'name' does not exist on type 'typeof A'.

Here the above solution does not even work, since A is considered as the class, not the constructor function...

@NN---
Copy link

NN--- commented Feb 19, 2015

It is easy to fix.
Just declare name:

interface Function {
    name: string;
}

// Using it
function f(): string { return f.name; }

The 'name' property is part of ES6 that's why you don't see it in lib.d.ts.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name

I think it will be declared in lib.es6.d.ts and you need to use ES6 generation option.

@mblinsitu
Copy link
Author

Thanks for the quick answer, I didn't realize I could extend Function.

Indeed, compiling for ES6 works without any added declaration, and adding the interface declaration works for ES5. And it also gives access to the class name as A.name.

@danquirk danquirk added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label Feb 19, 2015
@NN---
Copy link

NN--- commented Feb 19, 2015

Interfaces can be extended.
If you think from the JS perspective , then it is obvious.
You always can add any property to the object.
Therefore TS allows you to add properties to the existing interface.

@wcandillon
Copy link

I have class that looks like this:

class Iterator {

    protected position: Position;

    constructor(position: Position) {
        this.position = position;
    }

    toString(): string {
        return this.constructor.name;
    }
}

When I compile, I get the following error:
2339 Property 'name' does not exist on type 'Function'.

@danquirk
Copy link
Member

I suspect you have put your code augmenting the Function interface in an external module so your attempted augmentation does not exist in the same scope as the original definition. You need to write the augmentation in a global scope and then reference it.

@wcandillon
Copy link

yes at the end of the file I wrote:

export = Iterator;

Could you point me to a way I should rewrite my code? Thank you so much for the support @danquirk

@danquirk
Copy link
Member

@wcandillon put your extensions in a .d.ts that exists in the global scope (where the existing Function definition from lib.d.ts is) and reference that. So:

ext.d.ts:

interface Function {
    name: string
}

iterator.ts:

/// <reference path='ext.d.ts'/>

class Iterator {

    protected position: Position;

    constructor(position: Position) {
        this.position = position;
    }

    toString(): string {
        return this.constructor.name;
    }
}

export = Iterator;

@yagobilel
Copy link

hi,
i have this function :

getContact():any {
this._contactService.getContacts().then((contacts: Contact[]) => this.contacts = contacts);
}

When i compile, I get the following error in gulp:
error TS2339 : Property 'then' does not exist on type 'void'

@RyanCavanaugh
Copy link
Member

@yagobilel please post questions on Stack Overflow

@bennycode
Copy link
Contributor

@wcandillon You can also trick TypeScript by casting this into any which will prevent you from the TS2339: Property 'name' does not exist on type 'Function'. error.

Example:

    toString(): string {
        return (<any>this).constructor.name;
    }

@idchlife
Copy link

The question is: why it's not part of TypeScript? Doesn't Function has .name in specification?

@mhegazy
Copy link
Contributor

mhegazy commented Apr 13, 2017

The question is: why it's not part of TypeScript? Doesn't Function has .name in specification?

The name property is only available in ES6/ES2015-compliant engines. Include es2015 in your --lib value to get the property declaration.

@idchlife
Copy link

True. Thank you!

@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead
Projects
None yet
Development

No branches or pull requests

9 participants