Как сделать так, чтобы фабричная функция JSX стала глобальной для машинописного проекта? - PullRequest
0 голосов
/ 12 июня 2018

Я следую Руководству по TypeScript JSX , чтобы настроить JSX sans React и поиграться с ним в стороннем проекте.

Одна вещь, которая меня очень раздражаетЯ сталкиваюсь: я не могу найти упоминания о том, как глобально представить функцию фабрики JSX всему проекту.Кроме того (хотя это гораздо менее важно), моя JSX.IntrinsicElements структура также не отображается глобально.

Вот мой tsconfig:

{
    "compileOnSave": true,
    "compilerOptions": {
        "target": "es6",
        "lib": [
            "dom",
            "es2015"
        ],
        "experimentalDecorators": true,
        "jsx": "react",
        "jsxFactory": "generateElement",
        "sourceMap": true,
        "noImplicitAny": true,
        "pretty": true,
        "importHelpers": true,
        "outDir": "dist"
    },
    "include": ["./src/**/*.ts", "./src/**/*.tsx"]
}

Файл, в котором я объявляю generateElement:

export function generateElement(tag: string, attrs: string[]) {
    return document.createElement(tag)
}

declare namespace JSX {
    interface IntrinsicElements {
        image: any
    }
}

Файл, в котором я объявляю свой элемент image:

export function image(prop: {src: string}) {
    return (
        <img />
    )
}

И основная точка входа для проекта, куда я пытаюсь импортировать свой элемент:

import {image} from "./image";

image({src: "google.com"})

Ошибки:

src/image.tsx:13:9 - error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.

13         <img />
           ~~~~~~~


src/image.tsx:13:10 - error TS2304: Cannot find name 'generateElement'.

13         <img />
           ~~~~~~~

1 Ответ

0 голосов
/ 12 июня 2018

Если вы хотите сделать функцию глобальной, не используйте ключевое слово export, которое сделает текущий файл модулем, и, следовательно, функцию необходимо будет импортировать явно.Аналогично, пространство имен JSX должно быть глобальным, поэтому, если оно определено в модуле, оно должно быть явно объявлено в глобальном пространстве имен:

declare global {
    namespace JSX {
        interface IntrinsicElements {
            image: any
        }
    }
}

Если вы хотите пройти по глобальному маршруту, этобудет работать:

// jsxinfrastructure.ts
function generateElement(tag: string, attrs: string[]) {
    return document.createElement(tag)
}

declare namespace JSX {
    interface IntrinsicElements {
        image: any
    }
}

// usage.ts
export function image(prop: {src: string}) {
    return (
        <image />
    )
}

Если вы хотите, чтобы заводская функция jsx находилась внутри модуля, вам необходимо импортировать функцию:

// jsxinfrastructure.ts
export function generateElement(tag: string, attrs: string[]) {
    return document.createElement(tag)
}
declare global {
    namespace JSX {
        interface IntrinsicElements {
            image: any
        }
    }
}


// usage.ts
import { generateElement } from './jsxinfrastructure'
export function image(prop: {src: string}) {
    return (
        <image />
    )
}

Основная идея заключается в том, что заводская функция нуждаетсябыть доступным в контексте, где вы используете тег JSX (если вы можете вызвать generateElement jsx тоже будет работать).

...