-
Notifications
You must be signed in to change notification settings - Fork 196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support automatically determining if a string literal should be written for a property key or value in Writers.object #1160
Comments
@whalemare I wouldn't consider this totally broken. Right now, you need to explicitly write them as string literals. For example: const existedObject = {
id: `"some-id"`,
'"quote-key"': 2
} That said, I believe that the code could automatically determine that these should be string literals without having to do some complex parsing. I've renamed the title for the possible action item here. |
I write some hacky code that close my needs, maybe it can help somebody. P.s. for some reasons, I need modify parts with value for specific keys, so this code contains import Writer from 'code-block-writer'
import { match } from 'ts-pattern'
type Wrappers = { [key in string]: { start: string; end: string } }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function writeAny(writer: Writer, raw: any, wrappers: Wrappers = {}, needComma = false) {
match(typeof raw)
.with('object', () => writeObject(writer, raw, wrappers, true))
.with('string', () => writer.quote(raw))
.with('number', () => {
writer.write(`${raw}`)
})
.with('bigint', () => {
writer.write(`${raw}`)
})
.with('boolean', () => {
writer.write(raw ? 'true' : 'false')
})
.with('symbol', () => {
writer.quote(`${raw}`)
})
.otherwise(() => {
if (raw === null) {
writer.write('null')
} else if (raw === undefined) {
writer.write('undefined')
}
})
if (needComma) {
writer.write(',')
}
}
// eslint-disable-next-line @typescript-eslint/ban-types
export const writeObject = (writer: Writer, raw: object, wrappers: Wrappers = {}, needComma: boolean) => {
if (Array.isArray(raw)) {
writer.write(JSON.stringify(raw))
} else {
writer.write('{')
Object.keys(raw).forEach((key) => {
const spec = new RegExp('[^A-Za-z0-9]')
const hasSpecSymbols = spec.test(key)
writer.newLineIfLastNot()
if (hasSpecSymbols) {
writer.quote(key)
} else {
writer.write(key)
}
writer.write(`: ${wrappers[key]?.start ? wrappers[key].start : ''}`)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
writeAny(writer, raw[key], wrappers, needComma)
if (wrappers[key]?.end) {
writer.write(wrappers[key].end)
}
})
writer.write('}')
}
} Usage: sourceFile.addVariableStatement({
isExported: true,
declarationKind: VariableDeclarationKind.Const,
declarations: [
{
name: 'flavor',
initializer: (writer) => {
return writeAny(writer, someObject, {
// this will patch values with key 'textStyle' by inserting in start _StyleSheet.create(_ and in the end _),_)
textStyle: {
start: 'StyleSheet.create(',
end: '),',
},
})
},
},
],
}) |
Hello @dsherret , I'm facing similar issue with wrong generated property names. Currently I'm using Temporally I created function which detects if propname contains weird characters, if so, it'll wrap it to double quotes. const incorrectPropNameChars = [" ", "-", "."];
function sanitizePropName(propName: string) {
if (incorrectPropNameChars.some(char => propName.includes(char))) {
return `"${propName}"`;
}
return propName;
}
function createProperty(
name: string,
type: string,
doc: string,
isArray: boolean,
optional = true
): PropertySignatureStructure {
return {
kind: StructureKind.PropertySignature,
name: sanitizePropName(name),
docs: [doc],
hasQuestionToken: true,
type: isArray ? `Array<${type}>` : type,
};
} Yeah, the solution isn't the best, but it will work most time. Do you have any plans to implement it right into |
Yeah, I ran into the same issue, and I was hoping to be able to at least use a writer function to properly quote the value, but export function propertyKey(value: string): string | WriterFunction {
if (/^\w+$/.test(value)) {
return value;
}
// return JSON.stringify(value); // my current workaround
return (writer) => writer.quote(value);
} (and use |
Hmm, I found the following for ts-morph/packages/ts-morph/src/structurePrinters/enum/EnumMemberStructurePrinter.ts Lines 29 to 34 in cea07aa
as, with both this would change to // Adds quotes if structure is not a valid variable name
// AND the string is not enclosed in quotation marks
if (structure.name instanceof Function)
structure.name(writer)
else if (isValidVariableName(structure.name) || StringUtils.isQuoted(structure.name))
writer.write(structure.name);
else
writer.quote(structure.name); |
Re-opened by 055bf21 I completely forgot about computed property names and for some reason there wasn't a test for that. |
Describe the bug
Version: 10.1.0
I want to generate .ts file with variable content, that depend on my
existedObject
Writers
generate incorrect object representationTo Reproduce
Output:
Expected behavior
The text was updated successfully, but these errors were encountered: