jscodeshift TypeScript codemod - удалить общий тип, но сохранить обернутый тип
Сейчас я пытаюсь написать код, который удалит все $ReadOnly<T>
общий из кодовой базы TypeScript, сохраняя только T
(T
являясь объектом / объединением)
Пока это то, что я придумал
module.exports = (fileInfo, api) => {
const j = api.jscodeshift
const source = j(fileInfo.source)
source
.find(j.TSTypeAliasDeclaration)
.find(j.TSTypeReference)
.filter(x => {
return x.value.typeName.name === '$ReadOnly' && x.value.typeParameters.params[0].type === 'TSTypeLiteral'
})
.replaceWith(nodePath => {
const members = []
nodePath.value.typeParameters.params[0].members.forEach(x => {
members.push(j.tsPropertySignature(x.key, x.typeAnnotation))
})
return j.tsTypeLiteral(members)
})
return source
.toSource()
}
Идея состоит в том, чтобы изменить что-то вроде этого:
export type MyType = $ReadOnly<{
someProps: string,
}>
К тому, что:
export type MyType = {
someProps: string,
}
К сожалению, это то, что у меня получается, с дубликатом type
ключевое слово:
export type type MyType = {
someProps: string,
}
Есть идеи, что здесь могло пойти не так?
1 ответ
Его можно записать декларативно с putout кодом трансформатора (вы можете попробовать его в putout.cloudcmd.io ):
// type-updater.js
const {replaceWith} = require('putout').operator;
module.exports.report = () => '$ReadOnly generic should be removed';
module.exports.match = () => ({
'export type __a = __b': ({__b}, path) => {
return __b.name === '$ReadOnly';
}
});
module.exports.replace = () => ({
'export type __a = __b': (vars, path) => {
const typeAnnotationPath = path.get('declaration.typeAnnotation');
const paramPath = typeAnnotationPath.get('typeParameters.params.0');
replaceWith(typeAnnotationPath, paramPath);
return path;
},
});
Это Заменитель типа
putout plugin
.
Это изменит ввод:
// fixture/update-type.js
export type MyType = $ReadOnly<{
someProps: string,
}>
export type MyType2 = $WriteOnly<{
someProps: string,
}>
export type MyType1 = {
someProps: string,
}
На выходе:
// fixture/update-type-fix.js
export type MyType = {
someProps: string,
};
export type MyType2 = $WriteOnly<{
someProps: string,
}>
export type MyType1 = {
someProps: string,
}
Putout
имеет простой инструмент запуска тестов, поэтому вы можете протестировать его с помощью предопределенных приспособлений, используя:
// type-updater.spec.js
const test = require('@putout/test')(__dirname, {
'update-type': require('./type-updater'),
});
test('update-type: report', (t) => {
t.report('update-type', '$ReadOnly generic should be removed');
});
test('update-type: transform', (t) => {
t.transform('update-type');
t.end();
});
Чтобы запустить это
codemod
сохраните это в
~/.putout
и запустите свою кодовую базу с помощью:
putout .
Или сохраните в каталоге
your-project/codemods
и запустите:
putout --rulesdir codemods .