« first day (4441 days earlier)      last day (405 days later) » 

7:02 PM
@Bbrk24 this is why module augmentation is a thing in ts.
 
I've tried it before, it's always a pain and I never get it right the first time
or sometimes the object is an A | B and only B has the method in question, but TS doesn't even let you try to optional chain off of it
 
i mean
it's easy enough to check whether an object is B
(if ('key' in obj))
 
@ASCII-only If that passes it gives me a Record<'key', unknown> instead of being smart enough to figure out the type signature
 
@Bbrk24 no, because if it's already an A | B it narrows it to B.
assuming B has the key 'key' and A doesn't
 
And I can't check typeof x.foo == 'function' either, I have to first do in and then typeof
at some point it's easier to just tell TS "Shut up, I know what I'm doing"
(I've also been trying to avoid in after a vulnerability involving passing the string "__proto__" to different function in the codebase, but hasOwnProperty doesn't do type narrowing)
 
7:09 PM
well
i have a suspicion the reason why it does this is because it's not of type A | B
 
Object.keys, Object.entries, and Object#hasOwnProperty could have much better types than they do now
There's one place where I have a lot of as because these functions are so vaguely typed
 
@Bbrk24 nope, they can't.
@ASCII-only although this is more because of {} acting funny than anything
 
ive been doing some animation for a certain project, and i needed a scrolling bg. coding skills to the rescue lol
 
if a has literally any property at all then 'foo' in x works perfectly
 
settingsDescriptions.hasOwnProperty(key) doesn't narrow key to keyof typeof settingsDescriptions, so I have a lot of key as keyof typeof settingsDescriptions later in that function, for instance
or how about this one? Object.entries(settings) as [keyof IServerSettings, ValueOf<IServerSettings>][]
 
7:12 PM
const foo = (x: { y: number }) => {
    x.y = 42
}

const bar: { y: 0 } = { y: 0 }
foo(bar)

switch (bar.y) {
    case 0:
        console.log("always");
        break;
    default:
        const baz: never = bar.y;
        console.log("never", baz);
}
this is my favourite typescript snippet
 
aaaaaaaaaaaaaaaaaaaaaaaa british spelling
favorite is my favorite spelling, period
 
Those as's shouldn't necessarily be needed
 
@Bbrk24 yes, because this is not type safe.
@Bbrk24 also not type safe.
hence, they are absolutely needed
 
Why not?
 
7:14 PM
Okay, but these objects are constants created from object literals. It doesn't let you have extra keys in those
I think the epitome of "why is this as needed" is here:
const coerceSetting = <T extends keyof IServerSettings>(
  key: T,
  value: string
): IServerSettings[T] | undefined => {
  if (key === "dmHelp") {
    const num = Number(value);
    if ([0, 1, 2, 3, 4].includes(num)) return num as IServerSettings[T];
  } else if (key === "reactRemovalTimeout") {
    const num = Number(value);
    // It's official, TypeScript is dumb. It won't compile *without* this cast.
    if (Object.is(num, -0)) return 0 as IServerSettings[T];
    if (Number.isFinite(num) && num >= 0) return num as IServerSettings[T];
 
@ASCII-only wait wrong type, that's the type for Object.entries...
 
where IServerSettings is
interface IServerSettings {
  server: string;
  dmHelp: 0 | 1 | 2 | 3 | 4;
  reactRemovalTimeout: number;
}
Why do I need to cast 0 to number?
 
@Bbrk24 it doesn't let you, yes, but there is no way to mark a type as not having extra keys in typescript
@Bbrk24 beacuse typescript doesn't go through each possible type parameter because in many (if not most) cases, it's too slow
for many other cases (e.g. string), it's impossible to check them all
 
@ASCII-only That's fair I suppose. Something related to this has frustrated me before: there's no way, in the type system, to express an object returned from Object.create(null)
 
for other cases yet ("key1" | "key2" it will type-error anyway)
yeah typescript kinda doesn't do inheritance in general... apart from what it must, of course (class extends foo)
@Bbrk24 this is trivially solvable (although not type-safe) by using a single overload
 
7:19 PM
It's impossible to express "an object with no constructor" without explicitly saying constructor?: never. And then it complains if you're using a null-prototyped object as a Record
@ASCII-only Since you seem to have a better grasp on the type system than I do, why does it fail to compile when I remove the explicit generic parameter here? github.com/xsduan/conniebot/blob/master/src/conniebot.ts#L141
 
@Bbrk24 hm?
 
@ASCII-only Change it to Record<string, number> and it blows up
 
that's fair... but it's not like constructor?: never does much for type safety... does it?
function coerceSetting<T extends keyof IServerSettings>(
  key: T,
  value: string
): IServerSettings[T] | undefined
function coerceSetting(key: keyof IServerSettings, value: string): IServerSettings[keyof IServerSettings] | undefined {
}
 
@ASCII-only No, but the default behavior isn't any better: typescriptlang.org/play?target=6#code/…
Again, this makes sense in the general case, but not for null-prototyped objects
 
@Bbrk24 that's fair but who in their right mind would be explicitly accessing the field called constructor with a literal-typed string
like, no offense but that's a lot of hoops you'd have to jump through to intentionally trigger that error
 
7:24 PM
Someone who doesn't know about Object#constructor in the first place
 
well
if they don't know about Object#constructor i suspect they wouldn't even think of using constructor as a key
@Bbrk24 not sure, unfortunately i don't have the typings for discord.js memorized - what does the type parameter get inferred as?
 
@ASCII-only A union of literally every possibility ever, as if I had passed a dynamic string for the first argument
 
cuz it's definitely working for all the other .on which is kinda weird
 
just keyof WhateverItIs
for those two specifically it just gives up
 
this error does sometimes happen when the second argument is used as the discriminator
 
7:26 PM
Oh? Let me check the interface again, that might have something to do with it
 
but i don't feel like that's possible because, while they're both the only callbacks with != 1 argument... both of them have two arguments
 
Nope
messageUpdate: [oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage];
What's weird is that the tooltip shows the correct type if I remove it, but tsc doesn't figure it out
Wait, I did just update vs code. Maybe I have language server 5.0 and tsc 4.9? Hopefully updating typescript will fix it?
Still weird that TS 4.9 doesn't like this
 
huge thonk
i'm pretty sure djs has had these typings for years though
 
iirc it worked fine in an earlier version, like 4.5 or so, but then it broke in 4.8 or so
Also I'm now curious as to whether it's better to use arrow functions or .bind(this)
 
for performance? probably .bind(this), by a very narrow margin
 
7:32 PM
Okay yeah, updating typescript fixed it. Still weird that TS 4.9 dislikes it
 
yeah... it's weird that djs issues didn't mention anything about this though
but i mean... if it ain't broke anymore, don't fix it, lol
 
It's a TS problem, not a DJS problem. DJS has had blatant disregard for TS users in other things, sometimes intentionally not documenting its interfaces
  # Help string; can be object instead for embed. Object structure should match the EmbedData
  # interface. As of discord.js v14.0.3, this is intentionally undocumented (if you're on the
  # server, see the thread at discord.com/channels/222078108977594368/999317051782987797 ).
  # However, the interface is very similar to APIEmbed, which is documented at
  # discord-api-types.dev/api/discord-api-types-v10/interface/… .
 
this is why all the cool kids use discordeno
 
I want to be clear on something: I did not write the majority of this bot. I've been its primary maintainer for the past couple years, but was not for the majority of its existence.
 
7:58 PM
0
A: Sandbox for Proposed Challenges

mousetailVertically Aligned JSON formatting We have a question on JSON formatting on this site before, however, this one requires a different formatting convention. Arrays should be formatted with the first element on the same line as the opening [, and the final ] should be on the same line as the ]. All...

 
 
1 hour later…
9:03 PM
Is there any way to reply in room B to a message that was sent in room A? (And if not, would a room owner here be willing to move my reply as soon as I send it?)
 
not directly; best you could do I think is just link the message in room B so it oneboxes and then send your message below
 
9:47 PM
im closing everything i have for this one minute render
blender does really not like my computer
or the other way around
 
in The Sand Trap, 18 secs ago, by Unrelated String
:63267079 guessing this doesn't work then? :P
...yeah it doesn't
oneboxing a permalink and manually pinging them is probably the best option
 
10:12 PM
Which is too bad, because they haven't been in room B recently, so I can't ping them there. Ah well, I reckon I can do it this way:
 

« first day (4441 days earlier)      last day (405 days later) »