NativeScript:增强tns平台声明 [英] NativeScript: Augment tns-platform-declarations

查看:77
本文介绍了NativeScript:增强tns平台声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的NativeScript项目中,我想包含Android支持库中的RecyclerView. 我在app/App_Resources/Android/app.gradle中包括了依赖项:

// Uncomment to add recyclerview-v7 dependency
dependencies {
    compile 'com.android.support:recyclerview-v7:+'
}

git问题#2295 和其他相关问题中,我读到为本地android/ios库提供定义文件. 因此,我安装了它们并遵循 tns平台声明文档

我要编译以下示例代码段:

 import { ContentView } from "ui/content-view";

declare var android: any;

export class OptimizedListView extends ContentView {

  private _android: android.support.v7.widget.RecyclerView;

  public _createUI() {
    this._android = new android.support.v7.widget.RecyclerView(this._context);
  }

};
 

像上面一样声明var android会清理RecyclerView的第二个引用.但是,在RecyclerView的最高引用上仍然存在以下错误:

消息:'命名空间'android.support.v7.widget'没有导出的成员 "RecyclerView".

我还尝试声明RecyclerView类,但没有成功:

export declare class RecyclerView extends ContentView {}

我知道以下事实,即tns-platform-declarationsandroid.support.v7.widget之前都有定义.

将"noEmitOnError"设置为false的解决方法感觉不正确.

那么如何在没有编译问题的情况下将该声明扩展到android.support.v7.widget.RecyclerView?

版本:

  • "nativescript-dev-typescript":"^ 0.3.2"
  • "tns平台声明":"^ 2.4.0-2016-09-28-1"
  • 打字稿":"^ 2.1.1"
  • "tns-core-modules":下一个"

解决方案

最后,我完全不使用tns-platform-declarations,因为性能非常糟糕(特别是如果您的开发机中有< = 8GB RAM).

我的解决方案是定义一个自己的my-typings.d.ts文件(例如,在项目根目录中),在其中我定义了扩展类型RecyclerView.使用tsconfig.json默认值时,它应自动被tsc追上.否则,可以添加exclude/includefiles表达式.

然后您可以在其中放置/// <reference path="path/to/RecyclerView/file.d.ts" />,以便Typescript编译器可以找到以下ambient global namespace.

declare namespace android {

  namespace view {
    namespace ViewGroup {
      namespace LayoutParams {
        const MATCH_PARENT;
        const WRAP_CONTENT;
      }
    }
    class ViewGroup {

    }
  }

  namespace support.v7.widget {

    namespace RecyclerView {
      type AdapterImpl = {
        onCreateViewHolder(parent: android.view.ViewGroup, viewType: number): ViewHolder;
        onBindViewHolder(holder: android.support.v7.widget.RecyclerView.ViewHolder, position: number): void;
        getItemCount(): number
      };

      class Adapter {
        static extend(AdapterImpl): { new () }
      }

      class LayoutParams {
        constructor(width: any, height: any);
      }

      class ViewHolder {
        static extend: any;
      }
    }

    class RecyclerView {
      constructor(context: any);

      setAdapter(Adapter): void;
      setLayoutManager(LinearLayoutManager): void;
    }

    class LinearLayoutManager {
      constructor(context: any);
    }

  }
}

基本上,名称空间可用于模拟嵌套对象的属性(例如android.view.xxx).如果内部类是用Java定义的(Typescript似乎禁止嵌套class语句),这也是这种方式.

在实际使用类型的情况下(例如在android.view.ViewGroup中),我还必须定义一个与名称空间同名的类.否则,您将得到错误

没有导出的成员xxx

,即使使用export显式声明了类类型(也没有必要,因为您已经全局声明了名称空间).

对于用extend扩展本机Java类型的特殊情况,我为static extend(AdapterImpl): { new () }之类的相关类定义了一个静态方法,其返回类型可以用new实例化.

希望,这可以帮助其他遇到类似问题的人.

In my NativeScript project i want to include RecyclerView from Android Support Library. I included the dependency in app/App_Resources/Android/app.gradle :

// Uncomment to add recyclerview-v7 dependency
dependencies {
    compile 'com.android.support:recyclerview-v7:+'
}

From git issue#2295 and other related issues, i read that tns-platform-declarations can be included to offer definition files for native android/ios libraries. So i installed them and followed tns platform declarations documentation

I want to compile following example snippet:

import { ContentView } from "ui/content-view";

declare var android: any;

export class OptimizedListView extends ContentView {

  private _android: android.support.v7.widget.RecyclerView;

  public _createUI() {
    this._android = new android.support.v7.widget.RecyclerView(this._context);
  }

};

Declaring the var android like above cleans up the second reference of RecyclerView. But the following error on the top reference of RecyclerView remains:

message: 'Namespace 'android.support.v7.widget' has no exported member 'RecyclerView'.'

I also tried declaring the RecyclerView class without success:

export declare class RecyclerView extends ContentView {}

I am aware of the fact, that tns-platform-declarations has definitions until android.support.v7.widget.

Workaround of "noEmitOnError" set to false feels not right.

So how can i extend this declaration to android.support.v7.widget.RecyclerView without compile issues?

Versions:

  • "nativescript-dev-typescript": "^0.3.2"
  • "tns-platform-declarations": "^2.4.0-2016-09-28-1"
  • "typescript": "^2.1.1"
  • "tns-core-modules": "next"

解决方案

Finally I did not go with tns-platform-declarations at all, because performance was very bad (especially if you have <= 8GB RAM in your dev machine).

My solution was to define a own my-typings.d.ts file (e.g. in the project root dir) in which I defined the augmenting type RecyclerView. With tsconfig.json defaults it should be automatically be caught up by tsc. Otherwise exclude / include, or files expressions can be added.

Then you can place a /// <reference path="path/to/RecyclerView/file.d.ts" /> inside, so that the following ambient global namespace can be found by Typescript compiler.

declare namespace android {

  namespace view {
    namespace ViewGroup {
      namespace LayoutParams {
        const MATCH_PARENT;
        const WRAP_CONTENT;
      }
    }
    class ViewGroup {

    }
  }

  namespace support.v7.widget {

    namespace RecyclerView {
      type AdapterImpl = {
        onCreateViewHolder(parent: android.view.ViewGroup, viewType: number): ViewHolder;
        onBindViewHolder(holder: android.support.v7.widget.RecyclerView.ViewHolder, position: number): void;
        getItemCount(): number
      };

      class Adapter {
        static extend(AdapterImpl): { new () }
      }

      class LayoutParams {
        constructor(width: any, height: any);
      }

      class ViewHolder {
        static extend: any;
      }
    }

    class RecyclerView {
      constructor(context: any);

      setAdapter(Adapter): void;
      setLayoutManager(LinearLayoutManager): void;
    }

    class LinearLayoutManager {
      constructor(context: any);
    }

  }
}

Basically, namespaces can be used to emulate nested object properties (e.g. android.view.xxx). This is also the way, if inner classes are defined in Java (Typescript seems to forbid nested classstatements).

I also had to define a class with the same name as the namespace in cases, where I actually use the type (like in android.view.ViewGroup). Otherwise you get above error

no exported member xxx

, even if the class type is explicitly declared with export (and it's not necessary, because you have globally declared the namespace).

For the special case of extending native Java types with extend, I defined a static method for the relevant classes like static extend(AdapterImpl): { new () }, whose return type can be instantiated with new.

Hope, that helps other with similar issues.

这篇关于NativeScript:增强tns平台声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆