Search code examples
angularelectrones6-shim

Electron + Angular2 + es6-shim. Array has not the find function


I am trying to make a small program in electron with angular2 and it worked nice until i tried to use the find function on an array. There, I got an error

Property 'find' does not exist on type 'MyType[]'.

As a newbie, I couldn't understand the error, so I searched a little bit and I found out that the js engine that electron uses understands ES5 and not ES6.

Thats why se make a use on shimming with the es6-shim library in angular2. But, if so, I shouldn't get this error, should I?

My tsconfig.js file is this:

{
    "compilerOptions": {
        "target": "ES5",
        "module": "commonjs",
        "moduleResolution": "node",
        "removeComments": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "sourceMap": true,
        "noImplicitAny": false
    },
    "exclude": [
        "node_modules",
        "typings/index",
        "typings/index.d.ts"
    ],
    "compileOnSave": false,
    "buildOnSave": false
}

I make also use of the webpack, with the following configuration:

var path = require('path');
var webpack = require('webpack');
var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;

module.exports = {
    devtool: 'source-map',
    debug: true,

    entry: {
        'angular2': [
            'rxjs',
            'reflect-metadata',
            'angular2/core',
            'angular2/router',
            'angular2/http'
        ],
        'app': './app/app',
        'vendor': [
            'es6-shim',
            'es6-shim/es6-sham'
        ]
    },

    output: {
        path: __dirname + '/build/',
        publicPath: 'build/',
        filename: '[name].js',
        sourceMapFilename: '[name].js.map',
        chunkFilename: '[id].chunk.js'
    },

    resolve: {
        extensions: ['', '.ts', '.js', '.json', '.css', '.html']
    },

    module: {
        loaders: [{
            test: /\.ts$/,
            loader: 'ts',
            exclude: [/node_modules/]
        }]
    },

    plugins: [
        new CommonsChunkPlugin({
            name: 'angular2',
            filename: 'angular2.js',
            minChunks: Infinity
        }),
        new CommonsChunkPlugin({
            name: 'common',
            filename: 'common.js'
        }),
        new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js')
    ]
};

I suppose, there is misconfiguration in my project. But I cannot find it.

Thank you in advance.

UPDATE 1

Here are the contents of the package.json file:

{
    "name": "videos-for-kids",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "author": "Charalampos Chrysikopoulos",
    "license": "ISC",
    "scripts": {
        "build": "webpack --progress --profile --colors --display-error-details --display-cached",
        "watch": "webpack --watch --progress --profile --colors --display-error-details --display-cached",
        "start": "electron ."
    },
    "devDependencies": {
        "awesome-typescript-loader": "^0.15.10",
        "electron-prebuilt": "^1.2.6",
        "electron-reload": "^1.0.0",
        "ts-loader": "^0.7.2",
        "typescript": "^1.8.10",
        "webpack": "^1.12.9",
        "webpack-dev-server": "^1.14.0",
        "typings": "^1.3.1",
        "tslint": "^3.7.4",
        "ts-helpers": "^1.1.1",
        "imports-loader": "^0.6.5",
        "json-loader": "^0.5.4"
    },
    "dependencies": {
        "angular2": "2.0.0-beta.17",
        "systemjs": "0.19.26",
        "es6-shim": "^0.35.1",
        "reflect-metadata": "0.1.2",
        "rxjs": "^5.0.0-beta.6",
        "zone.js": "^0.6.12",
        "bootstrap": "^3.3.6"
    }
}

UPDATE 2

Here is also the class with the error:

import { Injectable } from 'angular2/core';
import { Http, Response } from 'angular2/http';
import { Observable } from 'rxjs/Observable';

import 'rxjs';

import {IVideo} from '../model/IVideo';

@Injectable()
export class VideoService {

    private _serviceUrl = 'file://pathTo/app/data/videos.json';

    constructor(private _http: Http) { }

    public getVideos(): Observable<IVideo[]> {
        return this._http.get(this._serviceUrl)
        .map((response: Response) => <IVideo[]> response.json())
        .catch(this.handleError);
    }

    private handleError(error: Response) {
        return Observable.throw(error.json().error || 'Server error');
    }

    getVideo(id: number): Observable<IVideo> {
       return this.getVideos()
            .map((videos: IVideo[]) => videos.find(v => v.id === id));
    }

}

Solution

  • Update So you gave me a clue that I disregarded and that led me down a rabbit hole that took a bit to get out of. I even built a plunker, to prove to myself that what you were trying to do was valid (even though it's obvious what you were doing would work). Sure enough I was able to use the Array.prototype.find() method without issue.

    //excerpt from plunker src/video.service.ts
    getVideo(id: number): Observable<IVideo> {
       return this.getVideos()
            .map((videos: IVideo[]) => videos.find(v => v.id === id));
    }
    

    The difference between the plunker and VS Code is that in the plunker SystemJS was actually performing the TypeScript transpile, where VS Code performs the transpile with the TypeScript compiler itself.

    However, you point out in the comments that you're not getting this error when you are performing the transpile. You're seeing this error in the VS Code "Problems" window before you even attempt to transpile the .ts code.

    I found that very strange, so I went back to the basics. I created a new VS Code project and I created a simple interface and instantiated an Array. Then I attempted to perform a .find() on that Array. VS Code immediately notified me in the Problems window that this method did not exist. The VS Code Problem window isn't using TypeScript to identify problems.

    VS Code is actually using another package called Typings, typings allow VS Code to extend it's own capability in parsing your code and providing intellisense. There are already hints in your package.json(devDependencies) file and in the tsconfig.json(exclude section) file as well that you have Typings.

    This means you have the tools installed but the project isn't configured. I am betting if you look in your "typings.json" file you should see an entry for "es6-shim". You should see something like this(if this doesn't exist create the file in your root and put that in it).

    {
    "globalDependencies": {
        "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd"
        }
    }
    

    In order for VS Code to use "es6-shim" it needs to be installed. The typings package has already been installed but the typing itself hasn't been installed in the project. To do this in VS Code on the toolbar select "View -> Integrated Terminal" (ctrl + `). You will see a command prompt. If you have Typings installed globally you can type in this command.

    typings install
    

    otherwise(it's installed locally)

    node_modules\.bin\typings install
    

    if either of those give you an error then Typings is not installed and you need to ensure that your package.json still has the dependency "typings". If it does then do "npm install", then repeat the step above.

    After that, restart VS Code and the error shouldn't exist anymore!

    Also you should update your tsconfig.json files "exclude" section to

    "exclude": [
        "node_modules",
        "typings/globals",//<----------
        "typings/index.d.ts"
    ]
    

    When is this error occurring? Is it at compile time or when you're running your Electron app? Also what version of TypeScript are you using? and what version of the Angular2 beta are you using? Your "package.json" file will tell you these things.

    If this is happening at compile time it means TypeScript doesn't know the "find" method for an array, which would be strange. TypeScript doesn't know about your webpack stuff, so upgrading your TypeScript version might do it (I am running '1.8.10' and it recognizes the 'find' method).

    If this is happening inside of Electron running, it could be a few things.

    It could be webpack is not loading the shim, you should be able to see if that is true by turning on the developer tool and looking under the Network tab and see if you see a request for the shim. If you don't see it, then you know it's a webpack issue.

    It could be that the es6-shim is missing the 'find' method inside of it. It might be best to use an alternative shim, in the link you would want to use the /client/shim.min.js file.

    It could be the version of the angular beta you're using didn't have that defined in the es6-shim. Which would be weird, but you could upgrade yourself the newest version of Angular2, in the example they use SystemJS to call bootstrap, so you might need to translate that to webpack. I am running @angular version '2.0.0-rc.4' without the shim and I can use the 'find' method at runtime.

    Also thinking it could be the version of Electron you're running (because I don't need the shim), I am running this version of Electron.