Reputation: 17835
I've got a rather strange problem. I'm extending a class, and for some reason none of the extended class's properties or methods are accessible. Here's my 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 actually does seem to successfully compile and run, but outputs an error about how it can't access game
in this.game
:
ERROR in ./src/my-game/MyGameState.ts
(17,14): error TS2339: Property 'game' does not exist on type 'MyGameState'.
Intellij is also confused. It seems to recognize that create()
is overriding a base class function, but also thinks game
doesn't exist.
It's perfectly happy to access game
off of Phaser.State
inside that class, though, as long as it's not the extended version. So this compiles and works fine:
const workingState = new Phaser.State();
workingState.game.boot();
Here's a foreshortened version of the class in phaser.d.ts
I'm extending:
declare module "phaser-ce" {
export = Phaser;
}
declare class Phaser {
class State {
game: Phaser.Game;
create(): void;
}
}
And the horribly hairy configuration I've got to get Phaser working with Typescript this well ...
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"]
}
}
Upvotes: 0
Views: 1216
Reputation: 17835
It seems like the fancy combined phaser my webpack config creates must be broken in some way shape or form.
I discovered I could prevent the typescript error by importing phaser in a different way:
import * as Phaser from "phaser-ce";
When imported this way I do not get errors and can use the members of the base class.
Upvotes: 1
Reputation: 251162
This isn't a specific answer for Phaser, but more a general "where to start" answer.
Step one is, check out this
:
export class MyGameState extends Phaser.State {
// More stuff [...]
create() {
console.log(this);
this.game.add.sprite(400, 300, "./assets/paddle.png");
}
}
One of the most common gotcas in TypeScript (and JavaScript) is that this
is not what you expect. This happens in TypeScript when a class method is invoked in a different context, such as an event.
If you find that this
is an element, or some other context, you can probably solve the problem with a fat-arrow (=>
), which preserves the lexical scope.
Upvotes: 1