Tomer Aberbach

Cursed Knowledge

Published ·

Cursed knowledge I have learned over time that I wish I never knew. Inspired by Immich’s Cursed Knowledge. The knowledge is ordered from most to least recently learned.

C# <code>JsonElement</code>’s <code>TryGet</code> methods are cursed permalinkC# JsonElement’s TryGet methods are cursed

JsonElement has GetByte/TryGetByte, GetDateTime/TryGetDateTime, GetDouble/TryGetDouble, etc. However, GetBoolean and GetString have no corresponding TryGet methods. What gives?

You’d expect Get methods to throw exceptions and TryGet methods to gracefully handle type mismatches, but that’s only half true. For example, the TryGetByte method:

  1. Returns true for JSON numbers that fit in a Byte
  2. Returns false for JSON numbers that don’t fit in a Byte
  3. Throws an exception for non-number JSON values (e.g. arrays and strings)

The TryGet methods are only graceful after confirming the JsonValueKind matches. This means that TryGetBoolean and TryGetString would behave identically to GetBoolean and GetString, respectively, because they have nothing to validate after the JsonValueKind. The methods don’t exist because they’d be pointless.

This behavior makes the TryGet methods almost always useless. You’re better off wrapping the Get methods in a try-catch.

TypeScript <code>readonly</code> properties are cursed permalinkTypeScript readonly properties are cursed

Marking a property as readonly tells TypeScript to disallow writing to it during type-checking.

However, it’s a nearly meaningless guardrail because TypeScript allows assigning a type with a readonly property to a type with a writable property.

type Person = {
  name: string
}
type ReadonlyPerson = {
  readonly name: string
}

const readonlyPerson: ReadonlyPerson = { name: `Tomer` }
// Cannot assign to 'name' because it is a read-only property.
readonlyPerson.name = `Tumor`

// Typechecks! 😱
const writablePerson: Person = readonlyPerson
writablePerson.name = `Tumor`

Hopefully one day readonly properties are properly enforced.

Maven dependency mediation is cursed permalinkMaven dependency mediation is cursed

When multiples versions of a dependency appear in the dependency tree, Maven chooses the version closest to the project root; not the highest version.

This behavior caused a bug in the OpenAI Java SDK.

JavaScript <code>Date</code>’s <code>setMonth</code> method is cursed permalinkJavaScript Date’s setMonth method is cursed

Calling setMonth(month)) doesn’t always update the date to the given month. For example, if the date is August 31, then setting the month to September will actually update the date to October 1. September only has 30 days, so the 31st day “overflows” to the next month.

This behavior caused a bug in Google Docs.

Python default parameter values are cursed permalinkPython default parameter values are cursed

A function’s default parameter values are evaluated once; not on each function call.

This means you shouldn’t use mutable values for a parameter’s default value:

def append_fun(list=[]):
    list.append('fun')
    return list

print(append_fun())
#=> ['fun']
print(append_fun())
#=> ['fun', 'fun']
print(append_fun())
#=> ['fun', 'fun', 'fun']

You have to apply the default in the function body instead:

def append_fun(list=None):
    if list is None:
        list = []
    list.append('fun')
    return list

print(append_fun())
#=> ['fun']
print(append_fun())
#=> ['fun']
print(append_fun())
#=> ['fun']

Java <code>URL</code>’s identity methods are cursed permalinkJava URL’s identity methods are cursed

A call to equals or hashCode may perform a blocking DNS lookup so that two URLs corresponding to the same IP address are considered equal.

This also means that using URL objects as HashMap keys will result in many DNS lookups.