You’ve defined every member of Animations to be either
A table of tables, or
A function
How do you know that Idle is a function and not a table? Do you check? If you did (e.g. with typeof), you can force the typechecker to ignore it by using the type assertion operator:
Before that, there’s a loop that changes every member of the table to be a function:
local animations: Animations = {
['Idle'] = {
{ ID = 9621052372; Speed = 0.25; Weight = 9 };
{ ID = 9650592168; Speed = 1; Weight = 1 };
}
}
-- ...
for animType: string,animTable in pairs(animations) do -- for each member of the animations table above,
local tracks: {
{
Track: AnimationTrack;
Speed: number;
Weight: number;
}
} = {}
for i,animationInfo in ipairs(animTable) do
-- not important
local tempAnimation = Instance.new('Animation')
tempAnimation.AnimationId = 'rbxassetid://'..animationInfo.ID
local animTrack = animator:LoadAnimation(tempAnimation)
tempAnimation:Destroy()
local speed = animationInfo.Speed
animTrack:AdjustSpeed(animationInfo.Speed)
animTrack.Name = i
table.insert(tracks, {
Track = animTrack;
Speed = speed;
Weight = animationInfo.Weight or 1;
})
end
animations[animType] = function() -- override the old entry to be a function
for i,v: AnimationTrack in ipairs(animator:GetPlayingAnimationTracks()) do
v:Stop(0.5)
end
while humanoid.State == animType do
local trackTable = getRandomValueFromNestedArray('Weight', tracks)
print(trackTable.Track)
trackTable.Track:Play(0.5)
trackTable.Track:AdjustSpeed(trackTable.Speed or 1)
task.wait(trackTable.Track.Length / (trackTable.Speed or 1))
print(trackTable.Track.Length, trackTable.Track.Length / (trackTable.Speed or 1))
trackTable.Track:Stop()
end
end
end
animations.Idle()
Assertion would work but I’m fairly certain that I’d have to do that for every single entry, wouldn’t I?
Also important to note that humanoid.State is a custom property from a humanoid wrapper which is always a string.
I would very strongly suggest making a new table instead of modifying the keyframes one. It will make your life easier and your code clearer. Immutable data is always much nicer to work with than mutable data.
If you absolutely must, you can torture the type system to do what you want:
-- intial assignment as just data, no functions
type AnimationInfo = {
[string]: {{ID: number; Speed: number?; Weight: number?}};
}
local animations: AnimationInfo = {
['Idle'] = {
{ ID = 9621052372; Speed = 0.25; Weight = 9 };
{ ID = 9650592168; Speed = 1; Weight = 1 };
}
}
-- ...
for animType: string,animTable in pairs(animations) do -- for each member of the animations table above,
-- ...
animations[animType] = function() -- override the old entry to be a function
-- ...
end :: any -- added type assertion here to pretend a function is a table
end
type Animations = {
[string]: () -> nil
}
-- fun hack to assign to an unrelated type
local animations = (animations :: any) :: Animations
animations.Idle() -- works without coercion, but you don't feel good about it :)
You’re right about the immutable data thing so I’ll work with that since it is a project where I’m working with another programmer, if something comes up where I’m unavailable to fix my own script and the other programmer has to fix it, I’d want my code to be clear. Just like if I were to fix theirs, I’d want it to be clear and easy to debug.