How to add types for third-party components in vue SFC template? - node.js

I am using volar+vue2+ts+composiiton api. In SFC templates, for custom components, volar is able to perform type checks and give the following message when some errors encountered. It benefits me a lot.
I wonder if the type check is also applicable on components from third-party packages such as element-ui. When hovering over tags like el-*(components from element-ui), volar says it has the type of any and type check is not available. For jsx components, one can add types to the IntrinsicElements in shims-tsx.d.ts. But IntrinsicElements doesn't work for SFC templates. Is it possible to add types for third-party components?
import Vue, { VNode } from 'vue';
declare global {
namespace JSX {
interface Element extends VNode {}
interface ElementClass extends Vue {}
interface IntrinsicElements {
// JSX can add types here
'el-button': any;
[elem: string]: any;
}
}
}
As #Finn said, element-ui has added types. Unfortunately, even though El* classes are imported and registered via vue's components option, volar seems to be unable to do type checks. Here ElHeader is expected to have a prop named height of type string. But it is assigned a number without any error message
The following code snippet comes from the source of element-ui
export declare class ElHeader extends ElementUIComponent {
/** Height of the header */
height: string
}

Element-ui for vue2 has added components type declare in package,
so volar's type checks follows the package's types declaration.

Related

module augmentation on node module that exports class: how to add instance property?

Update: I found exactly the same question on Reddit. Still looking for an answer though, since on Reddit, only a hack in node_modules/#types/ws/index.d.ts is proposed, which I rather not touch for obvious reasons.
I'm using the ws node module to create a socket server. Its typings are of the following structure:
declare class WebSocket extends events.EventEmitter {
// ...
}
declare namespace WebSocket {
// ...
}
export = WebSocket;
What is the correct way of extending the typings so that I can add an instance property id to a WebSocket class? I tried the following in a regular typescript(.ts) file:
class WebSocketServerWithId extends WebSocket {
id: number;
}
Which returns [ts] Type 'typeof WebSocket' is not a constructor function type. [2507]. I've also tried to use the approach in this Stackoverflow question with the same error as a result. I've read the documentation on declaration merging but still am confused.
Anyone knows hows to add an instance property to a class defined and exported in an external node module? (written in commonjs, meant to be executed in node alone).

Stripe + TypeScript: How to extend #types/stripe definitions for stripe-node?

I'm working on project, where we're using Stripe library for Node. We also want to use TypeScript on this project.
I've figured out that Stripe isn't providing official TypeScript definitions but I've found some community definitions #types/stripe on NPM. So I installed them and after a while I got an error:
Property 'sources' does not exist on type 'Stripe'.
Well there are missing some definitions, for example for this stripe.sources-related functionality.
I want to add missing definitions locally. So I need to extend this file:
#types/stripe/index.d.ts
I think that for the problem above I need:
to add property sources: Stripe.resources.Sources; to class Stripe,
to add class Sources to namespace resources,
to add missing function declarations to class Sources.
The problem is that I really don't know how. How should the .d.ts file with extensions look like? I've made many attempts according some examples and TypeScript docs but it always doesn't work. Do you have any idea?
I don't believe there's a way to augment the export-assigned Stripe class; the problem is similar to this open issue about augmenting a default-exported class. At this time, since you can't use augmentation, you'll have to fork the #types/stripe definitions for your project, and then you may as well make all the desired changes that way.
I think my colleague has found a solution that works for me. Here is how he made it:
import ST from 'stripe'
declare module 'stripe' {
namespace sources {
interface ISource extends IResourceObject {
...
}
interface ISourceCreationData {
...
}
}
namespace resources {
class Sources {
create(data: sources.ISourceCreationData): Promise<sources.ISource>;
retrieve(source: string, client_secret?: string): Promise<sources.ISource>;
}
}
class Stripe extends ST {
sources: ST.resources.Sources;
}
}

How to export typings along with a module?

I'm writing a module that adds some functionalities to testing suites our team is using. It's a project that has main typescript file, that wraps other exports from our project.
index.d.ts:
export * from "./OneModule"
export * from "./AnotherModule"
One of the modules has a functionality of adding new methods to Chai.js assertion library. This is achieved by using it's functions for adding new methods, for example:
assertion.addChainableMethod('newMethod', callback, chainCallback)
will add ability to write statements like expect(something).to.be.newMethod(). TypeScript though, doesn't recognize those new methods, since the type Assertion in #types/chai obviously doesn't have those functions.
I've created interface definition to be merged with the Chai Assertion like this:
declare namespace Chai {
interface Assertion {
newMethod(something: string): Assertion;
newMethod: Assertion;
}
}
The addChainableMethod adds new method so it can be also chaines as expect(something).to.be.newMethod.equals() that's why it has to be defined both as property and method.
The problem is, no matter how I add the above declaration to index.d.ts the new assertions aren't visible in the importing project. I suspect it's somehow wrapped in module namespace(but I might be very wrong about that). I know I can do #types/newAssertions and define them there, but that requires users to include 2 projects in package.json, and also requires our developers to handle 2 projects at once. How can I export both my Chai namespace extension and all the modules I have?
The best I've managed to do is something like that:
declare module 'my-module' {
function AddNewAssertions(chai: any, utils: any): void;
}
declare namespace Chai {
interface Assertion { //same as above }
}
But with this I cannot expose my other modules, and it works only when I'm only exposing AddNewAssertions function, which adds those assertions. This works perfectly though.
I knocked up a very basic test app for this, and I had some success with adding:
declare global {
namespace Chai {
interface Assertion {
newMethod(something: string): Assertion;
newMethod: Assertion;
}
}
}
This makes the extension visible in your other modules, not just the one with the declaration.

In puppet, how to retrieve variables inside a class scope from a different parameterized class

In the scope of one class, I need to be able to access a variable from another class. The variable is passed as a parameter, e.g.
class parameterized_class (
$param1,
) {
...
}
and
class other_class () {
include parameterized_class
Class['parameterized_class'] -> Class['other_class']
$local_var = $parameterized_class::param1
}
With an example usage of:
node default {
class { 'parameterized_class':
param1 => 'somevalue',
}
class { 'other_class': }
}
The above example does not work, as I get an error that looks roughly like:
Must pass param1 to
Class[Parameterized_class] at
/path/to/modules/parameterized_class/manifests/init.pp:1
on node localhost
Obviously, include is trying to declare parameterized_class without passing any parameters. But from the docs, I can see that include allows for a class to have been already previously declared, and since I have the parameterized_class declaration as a dependency of other_class, I don't understand how I could be getting this error.
I'm using Puppet 3.4.3, the version available on Ubuntu 14.04 Trusty
How should I go about retrieving the value of the $param1 in parameterized_class from within other_class's scope? Is it not possible to use include on parameterized classes?
According to the Puppet documentation (https://docs.puppet.com/puppet/3.5/lang_classes.html#include-like-behavior) you cannot use include-like declarations with mandatory parameters. In your case, what you can do is just not bother with the include since you've already handled that by declaring it in your node definition. Also, because both are declared in your node definition you would want to order them there as well.
As a side note not providing default values is a bad practice as is using variables across modules.

Using TypeScript Declaration For External JavaScript Library

I'm not sure if this extreme edge case or something but I cannot seem to find straight forward documentation on how to do this (or I'm just really not understanding what is available):
I am developing an ionic application and as part of that I need to use the ALKMaps JavaScript library (which is similar to Google Maps API). To do so, I created a local npm module and within that I created a alkmaps.d.ts file as recommended by https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html#objects-with-properties). However, I cannot seem to figure out how to properly import it into my angular code. The same document suggests that using <reference path=''> tags is not good but that is the only thing that seems to satisfy the tsc compiler.
My declaration file, alkmaps.d.ts, looks like (inside excluded for brevity):
declare namespace ALKMaps {
export class Map { ... }
...
}
And I was trying to import it into a file like:
import { ALKMaps } from 'alkmaps'; // Error: File '.../alkmaps.d.ts' is not a module
I also tried the following but got the same error.
import ALKMaps = require('alkmaps');
Using the reference tag seems to work within this module but then the project that utilizes this module still throws the "is not a module" error (that might warrant a separate question)
From https://github.com/Microsoft/TypeScript/issues/11420 I found the idea of using export = ALKMaps or export as namespace ALKMaps but adding those to my declaration file resulted in different errors instead.
Can anyone please explain in a straightforward way how to use declaration files representing external JS libraries in a typescript node module?
This is how I was able to get alkMaps into my Angular 2 app
Insert the script into the index.html file.
Declare an ALKMaps variable in the component that you are adding the map
imports .....
declare let ALKMaps : any;
#Component({
selector: 'show-map',
templateUrl: 'show-map.component.html'
})
export class ShowMapComponent implements Oninit{
map : any;
constructor() {
}
ngOnInit() {
ALKMaps.APIKey = "apiKey";
this.map = new ALKMaps.Map("map", {displayProjection: new ALKMaps.Projection("EPSG:4326")});
}
}
This will get the map to display and you can put different layers on the map, however the map does not display correctly. #Mike, if you were able to get further than this, will you please comment?
EDIT: The tiles on the image were elongated and not connected. After inspecting the css the main.css, after building, set a global property on the img element to:
img {
max-width:100%
}
The tiles for the map are originally set to 256% for the width. To correct the element, I changed the property for img in the style sheet.
show-map {
img {
max-width: 256%
}
}

Resources