Basically while porting from the old version I get lots of errors while using standard react HTML element properties. For example, whenever I try to add a title property to a button (to get a native tooltip) I get an error. While using tabIndex={-1} on it to avoid focusing via the tab key I get an error. While creating my own component that uses ButtonProps as a base I get that the style property is not defined and so on.
v0.xx types were ok in this regard since they extend their props with extends React.HTMLAttributes<{}> to get this behavior right (although it also meant that it got lots of potentionally invalid properties inserted into the type).
TS should not complain if we try to use standard html properties such as title and so on.
TS complains that these properties do not exist.
As an example:
<IconButton title='asdf' tabIndex={-1}/>
| Tech | Version |
|--------------|---------|
| Material-UI | latest beta |
| React | 15 |
| browser | Chrome 60 |
| TS | 2.5.2 |
For reference, react TS defines that interface as this one:
interface HTMLAttributes<T> extends DOMAttributes<T> {
// React-specific Attributes
defaultChecked?: boolean;
defaultValue?: string | string[];
suppressContentEditableWarning?: boolean;
// Standard HTML Attributes
accessKey?: string;
className?: string;
contentEditable?: boolean;
contextMenu?: string;
dir?: string;
draggable?: boolean;
hidden?: boolean;
id?: string;
lang?: string;
slot?: string;
spellCheck?: boolean;
style?: CSSProperties;
tabIndex?: number;
title?: string;
// Unknown
inputMode?: string;
is?: string;
radioGroup?: string; // <command>, <menuitem>
// WAI-ARIA
role?: string;
// RDFa Attributes
about?: string;
datatype?: string;
inlist?: any;
prefix?: string;
property?: string;
resource?: string;
typeof?: string;
vocab?: string;
// Non-standard Attributes
autoCapitalize?: string;
autoCorrect?: string;
autoSave?: string;
color?: string;
itemProp?: string;
itemScope?: boolean;
itemType?: string;
itemID?: string;
itemRef?: string;
results?: number;
security?: string;
unselectable?: boolean;
}
interface DOMAttributes<T> {
children?: ReactNode;
dangerouslySetInnerHTML?: {
__html: string;
};
// Clipboard Events
onCopy?: ClipboardEventHandler<T>;
onCopyCapture?: ClipboardEventHandler<T>;
onCut?: ClipboardEventHandler<T>;
onCutCapture?: ClipboardEventHandler<T>;
onPaste?: ClipboardEventHandler<T>;
onPasteCapture?: ClipboardEventHandler<T>;
// Composition Events
onCompositionEnd?: CompositionEventHandler<T>;
onCompositionEndCapture?: CompositionEventHandler<T>;
onCompositionStart?: CompositionEventHandler<T>;
onCompositionStartCapture?: CompositionEventHandler<T>;
onCompositionUpdate?: CompositionEventHandler<T>;
onCompositionUpdateCapture?: CompositionEventHandler<T>;
// Focus Events
onFocus?: FocusEventHandler<T>;
onFocusCapture?: FocusEventHandler<T>;
onBlur?: FocusEventHandler<T>;
onBlurCapture?: FocusEventHandler<T>;
// Form Events
onChange?: FormEventHandler<T>;
onChangeCapture?: FormEventHandler<T>;
onInput?: FormEventHandler<T>;
onInputCapture?: FormEventHandler<T>;
onReset?: FormEventHandler<T>;
onResetCapture?: FormEventHandler<T>;
onSubmit?: FormEventHandler<T>;
onSubmitCapture?: FormEventHandler<T>;
onInvalid?: FormEventHandler<T>;
onInvalidCapture?: FormEventHandler<T>;
// Image Events
onLoad?: ReactEventHandler<T>;
onLoadCapture?: ReactEventHandler<T>;
onError?: ReactEventHandler<T>; // also a Media Event
onErrorCapture?: ReactEventHandler<T>; // also a Media Event
// Keyboard Events
onKeyDown?: KeyboardEventHandler<T>;
onKeyDownCapture?: KeyboardEventHandler<T>;
onKeyPress?: KeyboardEventHandler<T>;
onKeyPressCapture?: KeyboardEventHandler<T>;
onKeyUp?: KeyboardEventHandler<T>;
onKeyUpCapture?: KeyboardEventHandler<T>;
// Media Events
onAbort?: ReactEventHandler<T>;
onAbortCapture?: ReactEventHandler<T>;
onCanPlay?: ReactEventHandler<T>;
onCanPlayCapture?: ReactEventHandler<T>;
onCanPlayThrough?: ReactEventHandler<T>;
onCanPlayThroughCapture?: ReactEventHandler<T>;
onDurationChange?: ReactEventHandler<T>;
onDurationChangeCapture?: ReactEventHandler<T>;
onEmptied?: ReactEventHandler<T>;
onEmptiedCapture?: ReactEventHandler<T>;
onEncrypted?: ReactEventHandler<T>;
onEncryptedCapture?: ReactEventHandler<T>;
onEnded?: ReactEventHandler<T>;
onEndedCapture?: ReactEventHandler<T>;
onLoadedData?: ReactEventHandler<T>;
onLoadedDataCapture?: ReactEventHandler<T>;
onLoadedMetadata?: ReactEventHandler<T>;
onLoadedMetadataCapture?: ReactEventHandler<T>;
onLoadStart?: ReactEventHandler<T>;
onLoadStartCapture?: ReactEventHandler<T>;
onPause?: ReactEventHandler<T>;
onPauseCapture?: ReactEventHandler<T>;
onPlay?: ReactEventHandler<T>;
onPlayCapture?: ReactEventHandler<T>;
onPlaying?: ReactEventHandler<T>;
onPlayingCapture?: ReactEventHandler<T>;
onProgress?: ReactEventHandler<T>;
onProgressCapture?: ReactEventHandler<T>;
onRateChange?: ReactEventHandler<T>;
onRateChangeCapture?: ReactEventHandler<T>;
onSeeked?: ReactEventHandler<T>;
onSeekedCapture?: ReactEventHandler<T>;
onSeeking?: ReactEventHandler<T>;
onSeekingCapture?: ReactEventHandler<T>;
onStalled?: ReactEventHandler<T>;
onStalledCapture?: ReactEventHandler<T>;
onSuspend?: ReactEventHandler<T>;
onSuspendCapture?: ReactEventHandler<T>;
onTimeUpdate?: ReactEventHandler<T>;
onTimeUpdateCapture?: ReactEventHandler<T>;
onVolumeChange?: ReactEventHandler<T>;
onVolumeChangeCapture?: ReactEventHandler<T>;
onWaiting?: ReactEventHandler<T>;
onWaitingCapture?: ReactEventHandler<T>;
// MouseEvents
onClick?: MouseEventHandler<T>;
onClickCapture?: MouseEventHandler<T>;
onContextMenu?: MouseEventHandler<T>;
onContextMenuCapture?: MouseEventHandler<T>;
onDoubleClick?: MouseEventHandler<T>;
onDoubleClickCapture?: MouseEventHandler<T>;
onDrag?: DragEventHandler<T>;
onDragCapture?: DragEventHandler<T>;
onDragEnd?: DragEventHandler<T>;
onDragEndCapture?: DragEventHandler<T>;
onDragEnter?: DragEventHandler<T>;
onDragEnterCapture?: DragEventHandler<T>;
onDragExit?: DragEventHandler<T>;
onDragExitCapture?: DragEventHandler<T>;
onDragLeave?: DragEventHandler<T>;
onDragLeaveCapture?: DragEventHandler<T>;
onDragOver?: DragEventHandler<T>;
onDragOverCapture?: DragEventHandler<T>;
onDragStart?: DragEventHandler<T>;
onDragStartCapture?: DragEventHandler<T>;
onDrop?: DragEventHandler<T>;
onDropCapture?: DragEventHandler<T>;
onMouseDown?: MouseEventHandler<T>;
onMouseDownCapture?: MouseEventHandler<T>;
onMouseEnter?: MouseEventHandler<T>;
onMouseLeave?: MouseEventHandler<T>;
onMouseMove?: MouseEventHandler<T>;
onMouseMoveCapture?: MouseEventHandler<T>;
onMouseOut?: MouseEventHandler<T>;
onMouseOutCapture?: MouseEventHandler<T>;
onMouseOver?: MouseEventHandler<T>;
onMouseOverCapture?: MouseEventHandler<T>;
onMouseUp?: MouseEventHandler<T>;
onMouseUpCapture?: MouseEventHandler<T>;
// Selection Events
onSelect?: ReactEventHandler<T>;
onSelectCapture?: ReactEventHandler<T>;
// Touch Events
onTouchCancel?: TouchEventHandler<T>;
onTouchCancelCapture?: TouchEventHandler<T>;
onTouchEnd?: TouchEventHandler<T>;
onTouchEndCapture?: TouchEventHandler<T>;
onTouchMove?: TouchEventHandler<T>;
onTouchMoveCapture?: TouchEventHandler<T>;
onTouchStart?: TouchEventHandler<T>;
onTouchStartCapture?: TouchEventHandler<T>;
// UI Events
onScroll?: UIEventHandler<T>;
onScrollCapture?: UIEventHandler<T>;
// Wheel Events
onWheel?: WheelEventHandler<T>;
onWheelCapture?: WheelEventHandler<T>;
// Animation Events
onAnimationStart?: AnimationEventHandler<T>;
onAnimationStartCapture?: AnimationEventHandler<T>;
onAnimationEnd?: AnimationEventHandler<T>;
onAnimationEndCapture?: AnimationEventHandler<T>;
onAnimationIteration?: AnimationEventHandler<T>;
onAnimationIterationCapture?: AnimationEventHandler<T>;
// Transition Events
onTransitionEnd?: TransitionEventHandler<T>;
onTransitionEndCapture?: TransitionEventHandler<T>;
}
Thanks for opening the issue!
We're doing this already 馃檪 but of course may missed some. BaseButton is a prime example for that. If I remember correctly we were unsure from what to extends since it can basically be any HTMLElement.
The issue with just inheriting from HTMLAttributes is that attributes, which a <button> has, are missing (type for example).
I already wrote about a possible solution here: https://github.com/callemall/material-ui/issues/8063#issuecomment-328431666
What do you think?
@sebald I am not sure what is going on here. I was using beta.8 and switched to beta.9 to see if anything would break so I could leave an issue if possible. I get this error, I did not change anything and don't use Chip anywhere in my project.
ERROR in /Users/marcuswhelan/work/Client/node_modules/material-ui/Chip/Chip.d.ts
(4,18): error TS2430: Interface 'ChipProps' incorrectly extends interface 'HTMLAttributes<HTMLDivElement>'.
Types of property 'tabIndex' are incompatible.
Type 'string | number | undefined' is not assignable to type 'number | undefined'.
Type 'string' is not assignable to type 'number | undefined'.
I wonder if this is related to this issue or I should create another issue.
Most helpful comment
For reference, react TS defines that interface as this one: