类型“{}”

时间:2018-04-25 08:36:39

标签: angular graphql apollo

在尝试在Angular和Apollo上创建一个简单的应用程序时,当我尝试使用ng build构建应用程序时,我偶然发现了一个问题,尽管该应用程序在localhost:4200上完美运行。该应用程序连接到Drupal 8 GraphQL服务器,连接正常。

构建时出现错误:

ERROR in app/idea-list/idea-list.component.ts(27,37): error TS2339: Property 'nodeQuery' does not exist on type '{}'. app/idea-list/idea-list.component.ts(28,36): error TS2339: Property 'loading' does not exist on type '{}'.

这是graphql.ts文件:

import {Article} from './type';
import gql from 'graphql-tag';

export const ALL_ARTICLES_QUERY = gql `
query {
   nodeQuery {
    entities {
      title: entityLabel
      ... on NodeArticle {
        body {
          value
        }
      }
    }
  }
}
`;

export interface AllArticlesQueryResponse {
    allArticles: Article[];
    loading: boolean;
}

这是GraphQL服务器的结果:

{
  "data": {
    "nodeQuery": {
      "entities": [
        {
          "title": "Article title.",
          "body": {
            "value": "<p>Article body value.</p>\r\n"
          }
        }
      ]
    }
  }
}

这是app/idea-list/idea-list.component.ts文件:

import { Component, OnInit } from '@angular/core';
import { Apollo } from 'apollo-angular';
import {Article } from '../type';
import {ALL_ARTICLES_QUERY, AllArticlesQueryResponse} from '../graphql';

@Component({
  selector: 'app-articles-list',
  templateUrl: './articles-list.component.html',
  styleUrls: ['./articles-list.component.css']
})
export class ArticlesListComponent implements OnInit {

  allArticles: Article[] = [];
  loading: boolean = true;

  constructor(private apollo: Apollo) { }

  ngOnInit() {
    this.apollo.watchQuery({
        query: ALL_ARTICLES_QUERY
    }).valueChanges.subscribe((response) => {
      console.log(response);
      this.allArticles = response.data.nodeQuery.entities;
      this.loading = response.data.loading;
    });
  }
}

更新: 浏览器的控制台没有错误,应用程序运行正常。但是,在构建应用程序时(当我在代码中更改某些内容时),这会发生在终端窗口中:

webpack: Compiling...
Date: 2018-04-25T09:09:23.622Z - Hash: b0a12071eaf44c16d874 - Time: 626ms
4 unchanged chunks
chunk {main} main.bundle.js (main) 36.3 kB [initial] [rendered]

webpack: Compiled successfully.
ERROR in src/app/articles-list/articles-list.component.ts(22,40): error TS2339: Property 'nodeQuery' does not exist on type '{}'.
src/app/articles-list/articles-list.component.ts(23,36): error TS2339: Property 'loading' does not exist on type '{}'.

同样的错误阻止我构建应用(ng build)。

其他信息(配置文件):

tsconfig.ts

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2017",
      "dom",
      "esnext"
    ]
  }
}

app/tsconfig.app.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app",
    "baseUrl": "./",
    "module": "es2015",
    "types": []
  },
  "exclude": [
    "test.ts",
    "**/*.spec.ts"
  ]
}

package.json

{
  "name": "petiangular",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^5.2.0",
    "@angular/common": "^5.2.0",
    "@angular/compiler": "^5.2.0",
    "@angular/core": "^5.2.0",
    "@angular/forms": "^5.2.0",
    "@angular/http": "^5.2.0",
    "@angular/platform-browser": "^5.2.0",
    "@angular/platform-browser-dynamic": "^5.2.0",
    "@angular/router": "^5.2.0",
    "apollo-angular": "^1.0.1",
    "apollo-angular-link-http": "^1.0.3",
    "apollo-cache-inmemory": "^1.1.12",
    "apollo-client": "^2.2.8",
    "bootstrap": "^3.3.7",
    "core-js": "^2.4.1",
    "graphql": "^0.13.2",
    "graphql-tag": "^2.9.1",
    "rxjs": "^5.5.6",
    "zone.js": "^0.8.19"
  },
  "devDependencies": {
    "@angular/cli": "~1.7.4",
    "@angular/compiler-cli": "^5.2.0",
    "@angular/language-service": "^5.2.0",
    "@types/jasmine": "~2.8.3",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "~6.0.60",
    "codelyzer": "^4.0.1",
    "jasmine-core": "~2.8.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~2.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~4.1.0",
    "tslint": "~5.9.1",
    "typescript": "~2.5.3"
  }
}

.angular.cli.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "project": {
    "name": "petiangular"
  },
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [
        "assets",
        "favicon.ico"
      ],
      "index": "index.html",
      "main": "main.ts",
      "polyfills": "polyfills.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.app.json",
      "testTsconfig": "tsconfig.spec.json",
      "prefix": "app",
      "styles": [
        "../node_modules/bootstrap/dist/css/bootstrap.css",
        "styles.css"
      ],
      "scripts": [],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      }
    }
  ],
  "e2e": {
    "protractor": {
      "config": "./protractor.conf.js"
    }
  },
  "lint": [
    {
      "project": "src/tsconfig.app.json",
      "exclude": "**/node_modules/**"
    },
    {
      "project": "src/tsconfig.spec.json",
      "exclude": "**/node_modules/**"
    },
    {
      "project": "e2e/tsconfig.e2e.json",
      "exclude": "**/node_modules/**"
    }
  ],
  "test": {
    "karma": {
      "config": "./karma.conf.js"
    }
  },
  "defaults": {
    "styleExt": "css",
    "component": {}
  }
}

2 个答案:

答案 0 :(得分:0)

这个编译错误可能是由于很多事情,但我怀疑它是在转换过程中发生的。

这个bug很可能源于Drupal 8 GraphQL。

但是有可能通过摆弄ECMAscript级别和/或JIT与AOT编译设置,你可以摆脱它。

但首先我建议你尝试部署应用程序。

进行生产构建,然后看看是否有轻微的故障实际上变成了一个showstopper并且崩溃了你的编译过程。

如果没有,那么您只需将其报告给Drupal 8 GraphQL here

之后停止关注它,因为它不会影响你的应用程序的生命周期,也不会出现在浏览器控制台中(对于最终用户来说,它不会存在)。

如果它确实使生产编译崩溃,那么我们将尝试不同的编译选项。

答案 1 :(得分:0)

您做错了几件事,所以让我解释一下。

首先,这是一个TypeScript问题,与运行时javascript问题无关,因此这就是为什么您在终端中看到它的原因。 TypeScript警告您属性nodeQuery在对象中不可用。这是因为对于TypeScript,此对象为空,没有属性。

import {Article} from '../type';
import {ALL_ARTICLES_QUERY, AllArticlesQueryResponse} from '../graphql';

export class ArticlesListComponent implements OnInit {

  allArticles: Article[] = [];
  loading: boolean = true;

  constructor(private apollo: Apollo) { }

  ngOnInit() {
    this.apollo.watchQuery({
        query: ALL_ARTICLES_QUERY
    }).valueChanges.subscribe((response) => {
      // response.data is {} (for typescript)
      // it means it's an empty object which has no properties
      this.allArticles = response.data.nodeQuery.entities;

      // another issues is that `loading` should be under `response` not `response.data`
      // it should be `response.loading`
      this.loading = response.data.loading;
    });
  }
}

Apollo不知道结果的接口是什么,但是它允许您定义它。我看到您已经定义了一个接口,让我们使用它:)

import {Article} from '../type';
import {ALL_ARTICLES_QUERY, AllArticlesQueryResponse} from '../graphql';

export class ArticlesListComponent implements OnInit {

  allArticles: Article[] = [];
  loading: boolean = true;

  constructor(private apollo: Apollo) { }

  ngOnInit() {
    // we define it as a first generic type of watchQuery method
    this.apollo.watchQuery<AllArticlesQueryResponse>({
        query: ALL_ARTICLES_QUERY
    }).valueChanges.subscribe((response) => {
      this.allArticles = response.data.nodeQuery.entities;
      this.loading = response.loading;
    });
  }
}

您不必手动编写界面,有一些工具可以帮您实现。在这里阅读我的答案:https://stackoverflow.com/a/52454671/4035768