无法访问 Typescript 中的基础 class 属性

Cannot access base class properties in Typescript

我遇到了一个很奇怪的问题。我正在扩展 class,出于某种原因,扩展 class 的属性或方法中的 none 是可访问的。这是我的 class:

import "pixi";
import "p2";
import Phaser from "phaser";

export class MyGameState extends Phaser.State {
    // More stuff [...]
    create() {
        this.game.add.sprite(400, 300, "./assets/paddle.png");
    }
}

这实际上似乎确实编译成功并且 运行,但是输出了一个关于它如何无法访问 this.game:

中的 game 的错误

ERROR in ./src/my-game/MyGameState.ts (17,14): error TS2339: Property 'game' does not exist on type 'MyGameState'.

Intellij也是一头雾水。它似乎认识到 create() 正在覆盖基础 class 函数,但也认为 game 不存在。

很高兴在 class 中访问 Phaser.Stategame,只要它不是扩展版本。所以这个编译并且工作正常:

const workingState = new Phaser.State();
workingState.game.boot();

这是 phaser.d.ts 中的 class 的缩短版本,我正在扩展:

declare module "phaser-ce" {
    export = Phaser;
}

declare class Phaser {
    class State {
        game: Phaser.Game;
        create(): void;
    }
}

我必须让 Phaser 与 Typescript 一起工作的可怕的毛茸茸的配置...

package.json

{
  "name": "MyGame",
  "main": "index.js",
  "scripts": {
    "dev": "webpack"
  },
  "devDependencies": {
    "browser-sync": "^2.18.12",
    "browser-sync-webpack-plugin": "^1.1.4",
    "expose-loader": "^0.7.3",
    "source-map-loader": "^0.2.1",
    "ts-loader": "^2.2.2",
    "tslint": "^5.5.0",
    "tslint-loader": "^3.5.3",
    "typescript": "^2.4.1",
    "webpack": "^2.6.1"
  },
  "dependencies": {
    "phaser-ce": "^2.8.1",
    "webfontloader": "^1.6.28"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "outDir": "./dist/",
    "sourceMap": true,
    "strictNullChecks": false,
    "module": "es6",
    "moduleResolution": "node",
    "target": "es5",
    "allowJs": true
  },
  "include": [
    "./src/"
  ]
}

webpack.config.js

var path = require('path')
var webpack = require('webpack')
var BrowserSyncPlugin = require('browser-sync-webpack-plugin')

// Phaser webpack config
var phaserModule = path.join(__dirname, '/node_modules/phaser-ce/')
var phaser = path.join(phaserModule, 'build/custom/phaser-split.js')
var pixi = path.join(phaserModule, 'build/custom/pixi.js')
var p2 = path.join(phaserModule, 'build/custom/p2.js')

var definePlugin = new webpack.DefinePlugin({
                                                __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true'))
                                            })

module.exports = {
    entry: {
        app: [
            path.resolve(__dirname, './src/main2.ts')
        ],
        vendor: ['pixi', 'p2', 'phaser', 'webfontloader']
    },
    devtool: 'source-map',
    output: {
        pathinfo: true,
        path: path.resolve(__dirname, 'dist'),
        publicPath: './dist/',
        filename: 'bundle.js'
    },
    watch: true,
    plugins: [
        definePlugin,
        new webpack.optimize.CommonsChunkPlugin(
            {name: 'vendor'/* chunkName= */, filename: 'vendor.bundle.js'/* filename= */}),
        new BrowserSyncPlugin({
                                  host: process.env.IP || 'localhost',
                                  port: process.env.PORT || 3000,
                                  server: {
                                      baseDir: ['./', './build']
                                  }
                              })
    ],
    module: {
        rules: [
            {test: /\.ts$/, enforce: 'pre', loader: 'tslint-loader', options: {emitErrors: true, failOnHint: true}},
            {test: /\.ts$/, loader: 'ts-loader'},
            {test: /pixi\.js/, use: ['expose-loader?PIXI']},
            {test: /phaser-split\.js$/, use: ['expose-loader?Phaser']},
            {test: /p2\.js/, use: ['expose-loader?p2']},
            {enforce: "pre", test: /\.js$/, loader: "source-map-loader"}
        ]
    },
    node: {
        fs: 'empty',
        net: 'empty',
        tls: 'empty'
    },
    resolve: {
        alias: {
            'phaser': phaser,
            'pixi': pixi,
            'p2': p2
        },
        extensions: [".ts", ".tsx", ".js", ".jsx"]
    }
}

这不是针对 Phaser 的特定答案,而是更笼统的 "where to start" 答案。

第一步是,查看 this:

export class MyGameState extends Phaser.State {
    // More stuff [...]
    create() {
        console.log(this);
        this.game.add.sprite(400, 300, "./assets/paddle.png");
    }
}

TypeScript(和 JavaScript)中最常见的问题之一是 this 不是您所期望的。当在不同的上下文(例如事件)中调用 class 方法时,在 TypeScript 中会发生这种情况。

如果你发现 this 是一个元素,或者其他一些上下文,你可能可以用粗箭头(=>)解决问题,which preserves the lexical scope.

看来我的 webpack 配置创建的花哨的组合相位器必须以某种方式被破坏。

我发现我可以通过以不同的方式导入移相器来防止打字稿错误:

import * as Phaser from "phaser-ce";

当以这种方式导入时,我不会出错并且可以使用基础 class 的成员。