primefaces / primevue

Next Generation Vue UI Component Library
https://primevue.org
MIT License
9.88k stars 1.19k forks source link

Api: Typing mismatch #3751

Closed Magiczne closed 1 year ago

Magiczne commented 1 year ago

Describe the bug

The Api.d.ts file exposes: FilterMatchMode and FilterMatchModeOptions. After updating to 3.25.0 the FilterMatchMode started behaving like a string, not like an enum, so we tried to switch to FilterMatchModeOptions which is exactly the same.

Unformtunately this error comes up:

"FilterMatchModeOptions" is not exported by "node_modules/primevue/api/api.esm.js", imported by "<redacted>".
1: import { FilterMatchModeOptions } from 'primevue/api'

Which is perfectly correct because when you look into api.esm.js file the only export is a FilterMatchMode

The same problem occurs for ToastSeverity in the same file.

Reproducer

none

PrimeVue version

3.25.0

Vue version

3.x

Language

TypeScript

Build / Runtime

Vite

Browser(s)

No response

Steps to reproduce the behavior

No response

Expected behavior

Types should be declared explicitely as enums, not as a variables typed as enums.

There should be only this in case of FilterMatchMode - preferably as const enum

export const enum FilterMatchMode {
    STARTS_WITH = 'startsWith',
    CONTAINS = 'contains',
    NOT_CONTAINS = 'notContains',
    ENDS_WITH = 'endsWith',
    EQUALS = 'equals',
    NOT_EQUALS = 'notEquals',
    IN = 'in',
    LESS_THAN = 'lt',
    LESS_THAN_OR_EQUAL_TO = 'lte',
    GREATER_THAN = 'gt',
    GREATER_THAN_OR_EQUAL_TO = 'gte',
    BETWEEN = 'between',
    DATE_IS = 'dateIs',
    DATE_IS_NOT = 'dateIsNot',
    DATE_BEFORE = 'dateBefore',
    DATE_AFTER = 'dateAfter'
}
Magiczne commented 1 year ago

Probably related to https://github.com/primefaces/primevue/pull/3728

NeluQi commented 1 year ago

I have the same

image

image

luke-z commented 1 year ago

Same thing happens for icons when using the constants described here

JeffreyNijs commented 1 year ago

The problem currently is that with the current implementation, TypeScript applications expect you to use the enum FilterMatchModeOptions. However, this does not exist in the .js files. Using FilterMatchModeOptions will cause your build to fail.

Additionally, my solution in https://github.com/primefaces/primevue/pull/3728 was the correct one, but this was changed after it was merged.

Goldenaries658 commented 1 year ago

Should be a simple quick fix to revert back to @JeffreyNijs solution which as far as I can tell is working perfectly.

To add this also means the docs are out of line with the implementation currently.

Themalni commented 1 year ago

I had the same problem with filters after updating to version 3.25.0, had to install previous version 3.20.0 to get rid of this issue.

mertsincan commented 1 year ago

Thanks a lot for the reports! I made some changes in JeffreyNijs' fix. Setting a value for the interface confused me a bit. So using the enum seemed more correct. Of course, I hadn't noticed that the enum was set to a value below. Sorry for the confusion!

new Api.d.ts ```typescript // Filter export const enum FilterMatchMode { STARTS_WITH = 'startsWith', CONTAINS = 'contains', NOT_CONTAINS = 'notContains', ENDS_WITH = 'endsWith', EQUALS = 'equals', NOT_EQUALS = 'notEquals', IN = 'in', LESS_THAN = 'lt', LESS_THAN_OR_EQUAL_TO = 'lte', GREATER_THAN = 'gt', GREATER_THAN_OR_EQUAL_TO = 'gte', BETWEEN = 'between', DATE_IS = 'dateIs', DATE_IS_NOT = 'dateIsNot', DATE_BEFORE = 'dateBefore', DATE_AFTER = 'dateAfter' } export const enum FilterOperator { AND = 'and', OR = 'or' } export declare namespace FilterService { export function filter(value: any, fields: string[], filterValue: any, filterMatchMode: string, filterLocale?: string): any[]; export interface filters { startsWith(value: any, filter: string, filterLocale?: string): boolean; contains(value: any, filter: string, filterLocale?: string): boolean; notContains(value: any, filter: string, filterLocale?: string): boolean; endsWith(value: any, filter: string, filterLocale?: string): boolean; equals(value: any, filter: string, filterLocale?: string): boolean; notEquals(value: any, filter: string, filterLocale?: string): boolean; in(value: any, filter: string): boolean; between(value: any, filter: string): boolean; lt(value: any, filter: string): boolean; lte(value: any, filter: string): boolean; gt(value: any, filter: string): boolean; gte(value: any, filter: string): boolean; dateIs(value: any, filter: string): boolean; dateIsNot(value: any, filter: string): boolean; dateBefore(value: any, filter: string): boolean; dateAfter(value: any, filter: string): boolean; } export function register(rule: string, fn: (...arg: any[]) => boolean): void; } // Icons export const enum PrimeIcons { ALIGN_CENTER = 'pi pi-align-center', ALIGN_JUSTIFY = 'pi pi-align-justify', ALIGN_LEFT = 'pi pi-align-left', ALIGN_RIGHT = 'pi pi-align-right', AMAZON = 'pi pi-amazon', ANDROID = 'pi pi-android', ANGLE_DOUBLE_DOWN = 'pi pi-angle-double-down', ANGLE_DOUBLE_LEFT = 'pi pi-angle-double-left', ANGLE_DOUBLE_RIGHT = 'pi pi-angle-double-right', ANGLE_DOUBLE_UP = 'pi pi-angle-double-up', ANGLE_DOWN = 'pi pi-angle-down', ANGLE_LEFT = 'pi pi-angle-left', ANGLE_RIGHT = 'pi pi-angle-right', ANGLE_UP = 'pi pi-angle-up', APPLE = 'pi pi-apple', ARROW_CIRCLE_DOWN = 'pi pi-arrow-circle-down', ARROW_CIRCLE_LEFT = 'pi pi-arrow-circle-left', ARROW_CIRCLE_RIGHT = 'pi pi-arrow-circle-right', ARROW_CIRCLE_UP = 'pi pi-arrow-circle-up', ARROW_DOWN = 'pi pi-arrow-down', ARROW_DOWN_LEFT = 'pi pi-arrow-down-left', ARROW_DOWN_RIGHT = 'pi pi-arrow-down-right', ARROW_LEFT = 'pi pi-arrow-left', ARROW_RIGHT = 'pi pi-arrow-right', ARROW_RIGHT_ARROW_LEFT = 'pi pi-arrow-right-arrow-left', ARROW_UP = 'pi pi-arrow-up', ARROW_UP_LEFT = 'pi pi-arrow-up-left', ARROW_UP_RIGHT = 'pi pi-arrow-up-right', ARROW_H = 'pi pi-arrows-h', ARROW_V = 'pi pi-arrows-v', ARROW_A = 'pi pi-arrows-alt', AT = 'pi pi-at', BACKWARD = 'pi pi-backward', BAN = 'pi pi-ban', BARS = 'pi pi-bars', BELL = 'pi pi-bell', BITCOIN = 'pi pi-bitcoin', BOLT = 'pi pi-bolt', BOOK = 'pi pi-book', BOOKMARK = 'pi pi-bookmark', BOOKMARK_FILL = 'pi pi-bookmark-fill', BOX = 'pi pi-box', BRIEFCASE = 'pi pi-briefcase', BUILDING = 'pi pi-building', CALENDAR = 'pi pi-calendar', CALENDAR_MINUS = 'pi pi-calendar-minus', CALENDAR_PLUS = 'pi pi-calendar-plus', CALENDAR_TIMES = 'pi pi-calendar-times', CALCULATOR = 'pi pi-calculator', CAMERA = 'pi pi-camera', CAR = 'pi pi-car', CARET_DOWN = 'pi pi-caret-down', CARET_LEFT = 'pi pi-caret-left', CARET_RIGHT = 'pi pi-caret-right', CARET_UP = 'pi pi-caret-up', CART_PLUS = 'pi pi-cart-plus', CHART_BAR = 'pi pi-chart-bar', CHART_LINE = 'pi pi-chart-line', CHART_PIE = 'pi pi-chart-pie', CHECK = 'pi pi-check', CHECK_CIRCLE = 'pi pi-check-circle', CHECK_SQUARE = 'pi pi-check-square', CHEVRON_CIRCLE_DOWN = 'pi pi-chevron-circle-down', CHEVRON_CIRCLE_LEFT = 'pi pi-chevron-circle-left', CHEVRON_CIRCLE_RIGHT = 'pi pi-chevron-circle-right', CHEVRON_CIRCLE_UP = 'pi pi-chevron-circle-up', CHEVRON_DOWN = 'pi pi-chevron-down', CHEVRON_LEFT = 'pi pi-chevron-left', CHEVRON_RIGHT = 'pi pi-chevron-right', CHEVRON_UP = 'pi pi-chevron-up', CIRCLE = 'pi pi-circle', CIRCLE_FILL = 'pi pi-circle-fill', CLOCK = 'pi pi-clock', CLONE = 'pi pi-clone', CLOUD = 'pi pi-cloud', CLOUD_DOWNLOAD = 'pi pi-cloud-download', CLOUD_UPLOAD = 'pi pi-cloud-upload', CODE = 'pi pi-code', COG = 'pi pi-cog', COMMENT = 'pi pi-comment', COMMENTS = 'pi pi-comments', COMPASS = 'pi pi-compass', COPY = 'pi pi-copy', CREDIT_CARD = 'pi pi-credit-card', DATABASE = 'pi pi-database', DELETELEFT = 'pi pi-delete-left', DESKTOP = 'pi pi-desktop', DIRECTIONS = 'pi pi-directions', DIRECTIONS_ALT = 'pi pi-directions-alt', DISCORD = 'pi pi-discord', DOLLAR = 'pi pi-dollar', DOWNLOAD = 'pi pi-download', EJECT = 'pi pi-eject', ELLIPSIS_H = 'pi pi-ellipsis-h', ELLIPSIS_V = 'pi pi-ellipsis-v', ENVELOPE = 'pi pi-envelope', ERASER = 'pi pi-eraser', EURO = 'pi pi-euro', EXCLAMATION_CIRCLE = 'pi pi-exclamation-circle', EXCLAMATION_TRIANGLE = 'pi pi-exclamation-triangle', EXTERNAL_LINK = 'pi pi-external-link', EYE = 'pi pi-eye', EYE_SLASH = 'pi pi-eye-slash', FACEBOOK = 'pi pi-facebook', FAST_BACKWARD = 'pi pi-fast-backward', FAST_FORWARD = 'pi pi-fast-forward', FILE = 'pi pi-file', FILE_EDIT = 'pi pi-file-edit', FILE_EXCEL = 'pi pi-file-excel', FILE_EXPORT = 'pi pi-file-export', FILE_IMPORT = 'pi pi-file-import', FILE_PDF = 'pi pi-file-pdf', FILE_WORD = 'pi pi-file-word', FILTER = 'pi pi-filter', FILTER_FILL = 'pi pi-filter-fill', FILTER_SLASH = 'pi pi-filter-slash', FLAG = 'pi pi-flag', FLAG_FILL = 'pi pi-flag-fill', FOLDER = 'pi pi-folder', FOLDER_OPEN = 'pi pi-folder-open', FORWARD = 'pi pi-forward', GIFT = 'pi pi-gift', GITHUB = 'pi pi-github', GLOBE = 'pi pi-globe', GOOGLE = 'pi pi-google', HASHTAG = 'pi pi-hashtag', HEART = 'pi pi-heart', HEART_FILL = 'pi pi-heart-fill', HISTORY = 'pi pi-history', HOURGLASS = 'pi pi-hourglass', HOME = 'pi pi-home', ID_CARD = 'pi pi-id-card', IMAGE = 'pi pi-image', IMAGES = 'pi pi-images', INBOX = 'pi pi-inbox', INFO = 'pi pi-info', INFO_CIRCLE = 'pi pi-info-circle', INSTAGRAM = 'pi pi-instagram', KEY = 'pi pi-key', LANGUAGE = 'pi pi-language', LINK = 'pi pi-link', LINKEDIN = 'pi pi-linkedin', LIST = 'pi pi-list', LOCK = 'pi pi-lock', LOCK_OPEN = 'pi pi-lock-open', MAP = 'pi pi-map', MAP_MARKER = 'pi pi-map-marker', MEGAPHONE = 'pi pi-megaphone', MICREPHONE = 'pi pi-microphone', MICROSOFT = 'pi pi-microsoft', MINUS = 'pi pi-minus', MINUS_CIRCLE = 'pi pi-minus-circle', MOBILE = 'pi pi-mobile', MONEY_BILL = 'pi pi-money-bill', MOON = 'pi pi-moon', PALETTE = 'pi pi-palette', PAPERCLIP = 'pi pi-paperclip', PAUSE = 'pi pi-pause', PAYPAL = 'pi pi-paypal', PENCIL = 'pi pi-pencil', PERCENTAGE = 'pi pi-percentage', PHONE = 'pi pi-phone', PLAY = 'pi pi-play', PLUS = 'pi pi-plus', PLUS_CIRCLE = 'pi pi-plus-circle', POUND = 'pi pi-pound', POWER_OFF = 'pi pi-power-off', PRIME = 'pi pi-prime', PRINT = 'pi pi-print', QRCODE = 'pi pi-qrcode', QUESTION = 'pi pi-question', QUESTION_CIRCLE = 'pi pi-question-circle', REDDIT = 'pi pi-reddit', REFRESH = 'pi pi-refresh', REPLAY = 'pi pi-replay', REPLY = 'pi pi-reply', SAVE = 'pi pi-save', SEARCH = 'pi pi-search', SEARCH_MINUS = 'pi pi-search-minus', SEARCH_PLUS = 'pi pi-search-plus', SEND = 'pi pi-send', SERVER = 'pi pi-server', SHARE_ALT = 'pi pi-share-alt', SHIELD = 'pi pi-shield', SHOPPING_BAG = 'pi pi-shopping-bag', SHOPPING_CART = 'pi pi-shopping-cart', SIGN_IN = 'pi pi-sign-in', SIGN_OUT = 'pi pi-sign-out', SITEMAP = 'pi pi-sitemap', SLACK = 'pi pi-slack', SLIDERS_H = 'pi pi-sliders-h', SLIDERS_V = 'pi pi-sliders-v', SORT = 'pi pi-sort', SORT_ALPHA_DOWN = 'pi pi-sort-alpha-down', SORT_ALPHA_ALT_DOWN = 'pi pi-sort-alpha-alt-down', SORT_ALPHA_UP = 'pi pi-sort-alpha-up', SORT_ALPHA_ALT_UP = 'pi pi-sort-alpha-alt-up', SORT_ALT = 'pi pi-sort-alt', SORT_ALT_SLASH = 'pi pi-sort-slash', SORT_AMOUNT_DOWN = 'pi pi-sort-amount-down', SORT_AMOUNT_DOWN_ALT = 'pi pi-sort-amount-down-alt', SORT_AMOUNT_UP = 'pi pi-sort-amount-up', SORT_AMOUNT_UP_ALT = 'pi pi-sort-amount-up-alt', SORT_DOWN = 'pi pi-sort-down', SORT_NUMERIC_DOWN = 'pi pi-sort-numeric-down', SORT_NUMERIC_ALT_DOWN = 'pi pi-sort-numeric-alt-down', SORT_NUMERIC_UP = 'pi pi-sort-numeric-up', SORT_NUMERIC_ALT_UP = 'pi pi-sort-numeric-alt-up', SORT_UP = 'pi pi-sort-up', SPINNER = 'pi pi-spinner', STAR = 'pi pi-star', STAR_FILL = 'pi pi-star-fill', STEP_BACKWARD = 'pi pi-step-backward', STEP_BACKWARD_ALT = 'pi pi-step-backward-alt', STEP_FORWARD = 'pi pi-step-forward', STEP_FORWARD_ALT = 'pi pi-step-forward-alt', STOP = 'pi pi-stop', STOPWATCH = 'pi pi-stop-watch', STOP_CIRCLE = 'pi pi-stop-circle', SUN = 'pi pi-sun', SYNC = 'pi pi-sync', TABLE = 'pi pi-table', TABLET = 'pi pi-tablet', TAG = 'pi pi-tag', TAGS = 'pi pi-tags', TELEGRAM = 'pi pi-telegram', TH_LARGE = 'pi pi-th-large', THUMBS_DOWN = 'pi pi-thumbs-down', THUMBS_DOWN_FILL = 'pi pi-thumbs-down-fill', THUMBS_UP = 'pi pi-thumbs-up', THUMBS_UP_FILL = 'pi pi-thumbs-up-fill', TICKET = 'pi pi-ticket', TIMES = 'pi pi-times', TIMES_CIRCLE = 'pi pi-times-circle', TRASH = 'pi pi-trash', TRUCK = 'pi pi-truck', TWITTER = 'pi pi-twitter', UNDO = 'pi pi-undo', UNLOCK = 'pi pi-unlock', UPLOAD = 'pi pi-upload', USER = 'pi pi-user', USER_EDIT = 'pi pi-user-edit', USER_MINUS = 'pi pi-user-minus', USER_PLUS = 'pi pi-user-plus', USERS = 'pi pi-users', VERIFIED = 'pi pi-verified', VIDEO = 'pi pi-video', VIMEO = 'pi pi-vimeo', VOLUME_DOWN = 'pi pi-volume-down', VOLUME_OFF = 'pi pi-volume-off', VOLUME_UP = 'pi pi-volume-up', WALLET = 'pi pi-wallet', WHATSAPP = 'pi pi-whatsapp', WIFI = 'pi pi-wifi', WINDOW_MAXIMIZE = 'pi pi-window-maximize', WINDOW_MINIMIZE = 'pi pi-window-minimize', WRENCH = 'pi pi-wrench', YOUTUBE = 'pi pi-youtube' } // Severity export const enum ToastSeverity { SUCCESS = 'success', INFO = 'info', WARN = 'warn', ERROR = 'error' } ```

If ok for everyone, I can release a patch version asap.

JeffreyNijs commented 1 year ago

image

optinforce commented 1 year ago

If ok for everyone, I can release a patch version asap.

Yes all good!

felixzapata commented 1 year ago

In order to resolve the typing issue with the new version, I have to change my tsconfig because of this error:

error TS2748: Cannot access ambient const enums when the '--isolatedModules' flag is provided.

42     value: '', matchMode: FilterMatchMode.STARTS_WITH,
                             ~~~~~~~~~~~~~~~

I am using the default Vite config, so isolatedModules is false. Vite recommends using true but also it says in its docs:

However, some libraries (e.g. [vue](https://github.com/vuejs/core/issues/1228)) don't work well with "isolatedModules": true. You can use "skipLibCheck": true to temporarily suppress the errors until it is fixed upstream.
Magiczne commented 1 year ago

Yes, that should be the case. File that provides const enums should not be ambient, but all the types in the primevue are done manually in the ambient context. Probably the solution would be to use TS from the ground up, but that's probably not happenning.

Probably using normal enum is enough, as this is only ambient context informing of types, not actually exporting them. @mertsincan could you address this as well in this ticket, or should we make another one?

mertsincan commented 1 year ago

Thanks a lot for the update! I know but I made an edit based on the following usage; runtime-core.d.ts in Vue

// line 853
export declare const enum ErrorCodes {
    SETUP_FUNCTION = 0,
    RENDER_FUNCTION = 1,
    WATCH_GETTER = 2,
    WATCH_CALLBACK = 3,
    WATCH_CLEANUP = 4,
    NATIVE_EVENT_HANDLER = 5,
    COMPONENT_EVENT_HANDLER = 6,
    VNODE_HOOK = 7,
    DIRECTIVE_HOOK = 8,
    TRANSITION_HOOK = 9,
    APP_ERROR_HANDLER = 10,
    APP_WARN_HANDLER = 11,
    FUNCTION_REF = 12,
    ASYNC_COMPONENT_LOADER = 13,
    SCHEDULER = 14
}

declare type ErrorTypes = LifecycleHooks | ErrorCodes;

There are many such uses in itself. I have no idea how to overcome this problem if we continue with enum for now. I guess the best way is to add the interface and properties string option that uses it. Exp;

...
export interface DataTableFilterMetaData {
    /**
     * Filter value
     */
    value: any;
    /**
     * Filter match mode
     */
    matchMode: string | 'startsWith' | 'contains' | 'notContains' | 'endsWith' | 'equals' | 'notEquals' | 'in' | 'lt' | 'lte' | 'gt' | 'gte' | 'between' | 'dateIs' | 'dateIsNot' | 'dateBefore' | 'dateAfter' | undefined;
}
..
export declare interface FilterMatchModeOptions {
    STARTS_WITH: string;
   ...
}

export const FilterMatchMode: FilterMatchModeOptions;
...

WDYT?

Magiczne commented 1 year ago

Yea, vue have the same kind of problem with const enums.

Basically option https://github.com/primefaces/primevue/pull/3728/files was the working one, but since that, normal enum could be working correctly, it's an ambient context, so it's not gonna be imported int o the app - the .js file will be.

JeffreyNijs commented 1 year ago

Yea, vue have the same kind of problem with const enums.

Basically option https://github.com/primefaces/primevue/pull/3728/files was the working one, but since that, normal enum could be working correctly, it's an ambient context, so it's not gonna be imported int o the app - the .js file will be.

Can confirm, a const enum error persists in 3.26.0. Maybe make a new issue for this?

Magiczne commented 1 year ago

Yes. Issue exists with PrimeVue 3.26 and isolatedModules flag - https://stackblitz.com/edit/vitejs-vite-jyp3fb?file=package.json,vite.config.ts,src%2FApp.vue&terminal=dev

I've made a test locally with replacing const enum with normal enum and it is working perfectly fine. As I said before - typings in PrimeVue are always included in ambient context files, which means that enum / const enum differente will not apply here, as it will be taken from the JS file. So either rollbacking to your solution or replacing every const enum with enum will be a solution.

mertsincan commented 1 year ago

Due to limitations, it has been fixed as in https://github.com/primefaces/primevue/issues/3806