Chu*_*Tey 3 leaflet typescript
我想使用带有Typescript https://github.com/CliffCloud/Leaflet.EasyButton/blob/master/src/easy-button.js的 easy-buttons插件,但它没有带有Typescript注释.
第一步是按原样使用示例代码而不使用Typescript注释,错误将在VS Code中开始点亮.
// sample.ts
L.easyBar([
L.easyButton('fa-file', function(btn, map){ }),
L.easyButton('fa-save', function(btn, map){ }),
L.easyButton('fa-edit', function(btn, map){ }),
L.easyButton('fa-dot-circle-o', function(btn, map){ })
]).addTo(map);
Run Code Online (Sandbox Code Playgroud)
我们创建了一个名为'easy-button.d.ts'的文件,并在我们的Typescript文件中引用它.
// sample.ts
import "./easy-button"
L.easyBar([
L.easyButton('fa-file', function(btn, map){ }),
L.easyButton('fa-save', function(btn, map){ }),
L.easyButton('fa-edit', function(btn, map){ }),
L.easyButton('fa-dot-circle-o', function(btn, map){ })
]).addTo(map);
Run Code Online (Sandbox Code Playgroud)
easy-button.d.ts中没有任何内容
// easy-button.d.ts
// empty for now
Run Code Online (Sandbox Code Playgroud)
错误说
error TS2339: Property 'easyBar' does not exist on type 'typeof L'.
error TS2339: Property 'easyButton' does not exist on type 'typeof L'.
Run Code Online (Sandbox Code Playgroud)
这是公平的,因为我们还没有定义这些.
如果你指的定义easyBar,并easyButton 在这里和这里,你会发现有一个神奇的一点在发生的历史原来的Javascript声明.似乎这两个函数没有任何参数,但实际上它们确实存在.
L.easyButton = function(/* args will pass automatically */){
var args = Array.prototype.concat.apply([L.Control.EasyButton],arguments);
return new (Function.prototype.bind.apply(L.Control.EasyButton, args));
};
Run Code Online (Sandbox Code Playgroud)
此功能会调用new的L.Control.EasyButton类.参数有点神秘,但你可以从这一行推断出它们:
initialize: function(icon, onClick, title, id)
Run Code Online (Sandbox Code Playgroud)
// easy-button.d.ts
declare namespace L {
function easyBar();
function easyButton();
}
Run Code Online (Sandbox Code Playgroud)
现在我们更接近了:
error TS2346: Supplied parameters do not match any signature of call target
Run Code Online (Sandbox Code Playgroud)
这很明显,因为我们提供了2个参数'fa-edit'和一个回调,easyButton但我们没有在参数中声明任何参数.我们现在的第二次尝试如下:
// easy-button.d.ts
declare namespace L {
function easyBar(buttons: any[]);
function easyButton(icon: string, onClick: (btn: any, map: any)=>void);
}
Run Code Online (Sandbox Code Playgroud)
现在所有的Typescript警告已经消失了.但还有更多可以做的事情.首先,easyButton实际上需要4个参数.这很容易修复 - 观察可选参数如何具有?后缀:
// easy-button.d.ts
declare namespace L {
function easyBar(buttons: any[]);
function easyButton(icon: string, onClick: (btn: any, map: any)=>void, title?: string, id?: string);
}
Run Code Online (Sandbox Code Playgroud)
该easyButton方法实际上返回一个L.Control.EasyButton实例.目前,Typescript定义意味着easyButton返回类型any.我们不希望这样!打字稿仅在我们提供打字时才有用.
declare namespace L {
function easyBar(buttons: Control.EasyButton[]): Control.EasyBar;
function easyButton(icon: string, onClick: (btn: any, map: any)=>void, title?: string, id?: string) : Control.EasyButton;
namespace Control {
class EasyButton { };
class EasyBar { };
}
}
Run Code Online (Sandbox Code Playgroud)
Typescript再次开始提供有用的警告:
error TS2339: Property 'addTo' does not exist on type 'EasyBar'.
Run Code Online (Sandbox Code Playgroud)
这是因为L.Control我们需要将EasyBar子类带入定义文件中.
declare namespace L {
function easyBar(buttons: Control.EasyButton[]): Control.EasyBar;
function easyButton(icon: string, onClick: (btn: any, map: any)=>void, title?: string, id?: string) : Control.EasyButton;
namespace Control {
class EasyButton extends L.Control { }
class EasyBar extends L.Control { }
}
}
Run Code Online (Sandbox Code Playgroud)
如果您尝试实例化一个新的EasyButton,代码完成表明您应该传入一个L.ControlOptions对象来配置它.实际上我们需要定义自己的选项.
declare namespace L {
function easyBar(buttons: Control.EasyButton[], options?: EasyBarOptions): Control.EasyBar;
function easyButton(icon: string, onClick: (btn: any, map: any)=>void, title?: string, id?: string) : Control.EasyButton;
interface EasyBarOptions {
position?: ControlPosition
id?: string
leafletClasses?: boolean
}
interface EasyButtonOptions {
position?: ControlPosition
id?: string
type?: 'replace'|'animate'
states?: any
leafletClasses?: boolean
tagName?: string
}
namespace Control {
class EasyButton extends L.Control {
constructor(options?: EasyButtonOptions)
}
class EasyBar extends L.Control {
constructor(options?: EasyBarOptions)
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我欺骗了这个states选项.我声明为any.实际上它应该是
interface EasyButtonOptions {
position?: ControlPosition
id?: string
type?: 'replace'|'animate'
states?: EasyButtonState[]
leafletClasses?: boolean
tagName?: string
}
interface EasyButtonState {
stateName: string
onClick: () => void
title: string
icon: string
}
Run Code Online (Sandbox Code Playgroud)
Typescript将为此插件的用户提供有用的评论.以下是我们如何提供文档的示例easyButton
/**
* Creates a easyButton
* @param icon e.g. fa-globe
* @param onClick the button click handler
* @param label on the button
* @param an id to tag the button with
* @example
* var helloPopup = L.popup().setContent('Hello World!');
*
* L.easyButton('fa-globe', function(btn, map){
* helloPopup.setLatLng(map.getCenter()).openOn(map);
* }).addTo( YOUR_LEAFLET_MAP );
*/
function easyButton(
icon: string,
onClick: (btn: Control.EasyButton, map: L.Map) => void,
title?: string,
id?: string): Control.EasyButton;
Run Code Online (Sandbox Code Playgroud)
(从Leaflet 1.2.0开始)删除命名空间声明:
declare namespace L {
Run Code Online (Sandbox Code Playgroud)
并用模块扩充替换它:
import * as L from 'leaflet'
declare module 'leaflet' {
Run Code Online (Sandbox Code Playgroud)
您的测试代码现在应该如下所示:
import * as L from 'leaflet'
import 'easy-button'
Run Code Online (Sandbox Code Playgroud)
打开node_modules\leaflet-easybutton\package.json并在style条目下方添加以下行:
"main": "src/easy-button.js",
"style": "src/easy-button.css",
"typings": "src/easy-button.d.ts",
Run Code Online (Sandbox Code Playgroud)
我们的移动easy-button.d.ts进入node_modules/leaflet-easybutton/src,并测试一切仍然有效.
然后提交拉取请求,以便每个人都可以从工作中受益!
| 归档时间: |
|
| 查看次数: |
2528 次 |
| 最近记录: |