Skip to content

feat(*): add params information to func proptypes where possible #79

Merged
merged 8 commits into from
Jun 19, 2018

Conversation

Heymdall
Copy link
Member

Добавил возможность генерировать более подробные типы для проптайпов-функций.
Получая на вход:

class Swipable extends React.Component {
  static propTypes = {
    /**
     * Функция запускаемая по свайпу.
     * @param {string} direction
     */
    onSwipe: Type.func
  };
}

будет генерироваться такое:

export interface SwipeableProps {
    readonly onSwipe: (direction?: any /*string*/) => any /*void*/;
}

Типы проставляются как any, так как полностью верить jsdoc-ам все же нельзя

@stepancar
Copy link
Contributor

@Heymdall если jsdoc не верить - то кому верить? Давай так:
если смогли определить примитивный тип - то его и ставим?

}

const paramsTypes = parsedDoc.params
.map(p => `${p.name}?: any /*${p.type ? p.type.name : 'any'}*/`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я бы тут вызывал stringifyType

@@ -66,11 +67,38 @@ function stringifyDescription(description, docblock) {
*/\n`;
}

function stringifyFunc(type, componentName, propName, description) {
try {
if (!description) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

можно вынести вверх за try

@@ -127,7 +157,7 @@ function stringifyComponentDefinition(info) {
export type ${propTypesTypeName} = Record<keyof ${propsInterfaceName}, Type.Validator<${propsInterfaceName}>>;

${stringifyDescription(info.description, info.docblock)}
export default class ${info.displayName} extends Component<${propsInterfaceName}, any> {
export default class ${info.displayName} extends Component<${propsInterfaceName}> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kokatsuna видимо придется обновить реакт дефинишены

@Heymdall
Copy link
Member Author

@stepancar согласен. Поменял немного все, теперь типы делаются из jsdoc-а так же, как и во всех остальных кейсах.



export interface AProps {
readonly optionalArray?: ReadonlyArray<any>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Heymdall
Если все поля readonly и поднята версия typescript - то не грех и generic утилитой Readonly воспользоваться чтоб читаемым было

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Или даже может стоить рискнуть и написать что-нибудь типа
type DeepReadonly = Readonly<{ [P in keyof T]: T[P] extends Array ? ReadonlyArray<DeepReadonly<T[P][0]>> : DeepReadonly<T[P]> }>;
Правда я думаю, что это еще не совсем корректно работает

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Было бы ништяк еслиб это работало
type DeepReadonly = T extends Array ? ReadonlyArray<DeepReadonly<T[0]>> : Readonly<{ [P in keyof T]: DeepReadonly<T[P]> }>

Copy link
Contributor

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Heymdall, я тут подумал, что сам интерфейс компонента лучше не делать readonly. Потому что ты можешь ведь динамически набивать проемы, перед тем как передать их компоненту ( не всегда ты можешь хорошо стипизировать литерал). Поэтому важно чтобы только this.props было deepreadonly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Фишка в том, что там, где ожидается ридонли можно кинуть обычный, а наоборот - нет.
Ридонли же по сути сабсет обычных типов.
Начал приделывать это изначально именно из-за того что пришлось кастовать ридонли типы из редакс стейта до обычных, когда кидал их в наши компоненты.
Поэтому и захотелось сделать интерфейс компонента ридонли

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А про DeepReadonly согласен, обновил

}

const DEPP_READONLY_TYPES = `
type Primitive = string | number | boolean | undefined | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Мне кажется что это можно куда-то засунуть и импортить

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ну оно как бы можно, но сильно усложняет весь этот процесс. Либо выносить это в отдельную либу, но тогда непонятно как это как зависимость делать. Мы же не привязываемся к конкретной библиотеке тут. Этот код вообще даже не знает куда все это будет записано, надо либо мучаться с относительными импортами тут, либо заставлять пользователей библиотеки ставить как зависимость что-то, что экспортами этот тип. А вот профита от этого никакого нету

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Heymdall согласен. Может воткнут этот хэлпер в ts.core.

@Heymdall Heymdall merged commit f1e2aae into master Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants